def generate_pajek_(G): import warnings from networkx.utils import is_string_like, open_file, make_str if G.name == '': name = 'NetworkX' else: name = G.name # Apparently many Pajek format readers can't process this line # So we'll leave it out for now. # yield '*network %s'%name # write nodes with attributes yield '*vertices %s' % (G.order()) nodes = list(G) # make dictionary mapping nodes to integers nodenumber = dict(zip(nodes, range(1, len(nodes) + 1))) for n in nodes: # copy node attributes and pop mandatory attributes # to avoid duplication. na = G.nodes.get(n, {}).copy() x = na.pop('x', 0.0) y = na.pop('y', 0.0) id = int(na.pop('id', nodenumber[n])) nodenumber[n] = id shape = na.pop('shape', 'ellipse') s = ' '.join(map(make_qstr, (id, n, x, y, shape))) # only optional attributes are left in na. for k, v in na.items(): if is_string_like(v) and v.strip() != '': s += ' %s %s' % (make_qstr(k), make_qstr(v)) else: warnings.warn('Node attribute %s is not processed. %s.' % (k, 'Empty attribute' if is_string_like(v) else 'Non-string attribute')) s = s.replace('\n', ' ') yield s # write edges with attributes if G.is_directed(): yield '*arcs' else: yield '*edges' for u, v, edgedata in G.edges(data=True): d = edgedata.copy() value = d.pop('weight', 1.0) # use 1 as default edge value s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value))) for k, v in d.items(): if is_string_like(v) and v.strip() != '': s += ' %s %s' % (make_qstr(k), make_qstr(v)) s += ' ' else: warnings.warn('Edge attribute %s is not processed. %s.' % (k, 'Empty attribute' if is_string_like(v) else 'Non-string attribute')) yield s
def generate_pajek(G): """Generate lines in Pajek graph format. Parameters ---------- G : graph A Networkx graph References ---------- See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm for format information. """ if G.name=='': name='NetworkX' else: name=G.name yield '*network %s'%name # write nodes with attributes yield '*vertices %s'%(G.order()) nodes = G.nodes() # make dictionary mapping nodes to integers nodenumber=dict(zip(nodes,range(1,len(nodes)+1))) for n in nodes: na=G.node.get(n,{}) x=na.get('x',0.0) y=na.get('y',0.0) id=int(na.get('id',nodenumber[n])) nodenumber[n]=id shape=na.get('shape','ellipse') s=' '.join(map(make_str,(id,n,x,y,shape))) for k,v in na.items(): if is_string_like(v): # add quotes to any values with a blank space if " " in v: v="\"%s\""%v s+=' %s %s'%(k,v) yield s # write edges with attributes if G.is_directed(): yield '*arcs' else: yield '*edges' for u,v,edgedata in G.edges(data=True): d=edgedata.copy() value=d.pop('weight',1.0) # use 1 as default edge value s=' '.join(map(make_str,(nodenumber[u],nodenumber[v],value))) for k,v in d.items(): if is_string_like(v): # add quotes to any values with a blank space if " " in v: v="\"%s\""%v s+=' %s %s'%(k,v) yield s
def generate_pajek(G): """Generate lines in Pajek graph format. Parameters ---------- G : graph A Networkx graph References ---------- See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm for format information. """ if G.name == '': name = 'NetworkX' else: name = G.name yield '*network %s' % name # write nodes with attributes yield '*vertices %s' % (G.order()) nodes = G.nodes() # make dictionary mapping nodes to integers nodenumber = dict(zip(nodes, range(1, len(nodes) + 1))) for n in nodes: na = G.node.get(n, {}) x = na.get('x', 0.0) y = na.get('y', 0.0) id = int(na.get('id', nodenumber[n])) nodenumber[n] = id shape = na.get('shape', 'ellipse') s = ' '.join(map(make_str, (id, n, x, y, shape))) for k, v in na.items(): if is_string_like(v): # add quotes to any values with a blank space if " " in v: v = "\"%s\"" % v s += ' %s %s' % (k, v) yield s # write edges with attributes if G.is_directed(): yield '*arcs' else: yield '*edges' for u, v, edgedata in G.edges(data=True): d = edgedata.copy() value = d.pop('weight', 1.0) # use 1 as default edge value s = ' '.join(map(make_str, (nodenumber[u], nodenumber[v], value))) for k, v in d.items(): if is_string_like(v): # add quotes to any values with a blank space if " " in v: v = "\"%s\"" % v s += ' %s %s' % (k, v) yield s
def add_prefix1(x): prefix = rename[1] if is_string_like(x): name = prefix + x else: name = prefix + repr(x) return name
def parse_p2g(lines): """Parse p2g format graph from string or iterable. Returns an MultiDiGraph. """ if is_string_like(lines): lines=iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) description = lines.next() # are multiedges (parallel edges) allowed? G=networkx.MultiDiGraph(name=description,selfloops=True) nnodes,nedges=map(int,lines.next().split()) nodelabel={} nbrs={} # loop over the nodes keeping track of node labels and out neighbors # defer adding edges until all node labels are known for i in range(nnodes): n=lines.next() nodelabel[i]=n G.add_node(n) nbrs[n]=map(int,lines.next().split()) # now we know all of the node labels so we can add the edges # with the correct labels for n in G: for nbr in nbrs[n]: G.add_edge(n,nodelabel[nbr]) return G
def parse_p2g(lines): """Parse p2g format graph from string or iterable. Returns an XDiGraph.""" if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) description = lines.next() # are multiedges (parallel edges) allowed? G = networkx.XDiGraph(name=description, selfloops=True) nnodes, nedges = map(int, lines.next().split()) nodelabel = {} nbrs = {} # loop over the nodes keeping track of node labels and out neighbors # defer adding edges until all node labels are known for i in range(nnodes): n = lines.next() nodelabel[i] = n G.add_node(n) nbrs[n] = map(int, lines.next().split()) # now we know all of the node labels so we can add the edges # with the correct labels for n in G: for nbr in nbrs[n]: G.add_edge(n, nodelabel[nbr]) return G
def write_pajek(G, path): """Write in Pajek format to path. Parameters ---------- G : graph A networkx graph path : file or string File or filename to write. Filenames ending in .gz or .bz2 will be compressed. Examples -------- >>> G=nx.path_graph(4) >>> nx.write_pajek(G, "test.net") """ fh=_get_fh(path,mode='w') if G.name=='': name="NetworkX" else: name=G.name fh.write("*network %s\n"%name) # write nodes with attributes fh.write("*vertices %s\n"%(G.order())) nodes = G.nodes() # make dictionary mapping nodes to integers nodenumber=dict(zip(nodes,range(1,len(nodes)+1))) for n in nodes: na=G.node[n].copy() x=na.pop('x',0.0) y=na.pop('y',0.0) id=int(na.pop('id',nodenumber[n])) nodenumber[n]=id shape=na.pop('shape','ellipse') fh.write("%d \"%s\" %f %f %s "%(id,n,float(x),float(y),shape)) for k,v in na.items(): fh.write("%s %s "%(k,v)) fh.write("\n") # write edges with attributes if G.is_directed(): fh.write("*arcs\n") else: fh.write("*edges\n") for u,v,edgedata in G.edges(data=True): d=edgedata.copy() value=d.pop('weight',1.0) # use 1 as default edge value fh.write("%d %d %f "%(nodenumber[u],nodenumber[v],float(value))) for k,v in d.items(): if is_string_like(v): # add quotes to any values with a blank space if " " in v: v="\"%s\""%v fh.write("%s %s "%(k,v)) fh.write("\n")
def string_item(k,v,indent): # try to make a string of the data if type(v)==dict: v=listify(v,indent,2) elif is_string_like(v): v='"%s"'%v elif type(v)==bool: v=int(v) return "%s %s"%(k,v)
def parse_leda(lines): """Read graph in LEDA format from string or iterable. Parameters ---------- lines : string or iterable Data in LEDA format. Returns ------- G : NetworkX graph Examples -------- G=nx.parse_leda(string) References ---------- .. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html """ if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([ line.rstrip('\n') for line in lines if not (line.startswith('#') or line.startswith('\n') or line == '') ]) for i in range(3): next(lines) # Graph du = int(next(lines)) # -1=directed, -2=undirected if du == -1: G = nx.DiGraph() else: G = nx.Graph() # Nodes n = int(next(lines)) # number of nodes node = {} for i in range(1, n + 1): # LEDA counts from 1 to n symbol = next(lines).rstrip().strip('|{}| ') if symbol == "": symbol = str(i) # use int if no label - could be trouble node[i] = symbol G.add_nodes_from([s for i, s in node.items()]) # Edges m = int(next(lines)) # number of edges for i in range(m): try: s, t, reversal, label = next(lines).split() except: raise NetworkXError('Too few fields in LEDA.GRAPH edge %d' % (i + 1)) # BEWARE: no handling of reversal edges G.add_edge(node[int(s)], node[int(t)], label=label[2:-2]) return G
def make_qstr(t): """Return the string representation of t. Add outer double-quotes if the string has a space. """ if not is_string_like(t): t = str(t) if " " in t: t=r'"%s"'%t return t
def make_qstr(t): """Return the string representation of t. Add outer double-quotes if the string has a space. """ if not is_string_like(t): t = str(t) if " " in t: t = r'"%s"' % t return t
def string_item(k, v, indent): # try to make a string of the data if type(v) == dict: v = listify(v, indent, 2) elif is_string_like(v): v = '"%s"' % v elif type(v) == bool: v = int(v) return "%s %s" % (k, v)
def string_item(k,v,indent): # try to make a string of the data if type(v) == dict: v = listify(v, indent, 2) elif is_string_like(v): v = '"{0}"'.format(escape(v, quote=True)) #v = '"{0}"'.format(v, quote=True) elif type(v) == bool: v = int(v) return "{0} {1}".format(k,v)
def string_item(k, v, indent): # try to make a string of the data if type(v) == dict: v = listify(v, indent, 2) elif is_string_like(v): v = '"{0}"'.format(escape(v, quote=True)) #v = '"{0}"'.format(v, quote=True) elif type(v) == bool: v = int(v) return "{0} {1}".format(k, v)
def parse_leda(lines): """Read graph in LEDA format from string or iterable. Parameters ---------- lines : string or iterable Data in LEDA format. Returns ------- G : NetworkX graph Examples -------- G=nx.parse_leda(string) References ---------- .. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html """ if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines if not (line.startswith('#') or line.startswith('\n') or line == '')]) for i in range(3): next(lines) # Graph du = int(next(lines)) # -1=directed, -2=undirected if du == -1: G = nx.DiGraph() else: G = nx.Graph() # Nodes n = int(next(lines)) # number of nodes node = {} for i in range(1, n + 1): # LEDA counts from 1 to n symbol = next(lines).rstrip().strip('|{}| ') if symbol == "": symbol = str(i) # use int if no label - could be trouble node[i] = symbol G.add_nodes_from([s for i, s in node.items()]) # Edges m = int(next(lines)) # number of edges for i in range(m): try: s, t, reversal, label = next(lines).split() except: raise NetworkXError('Too few fields in LEDA.GRAPH edge %d' % (i + 1)) # BEWARE: no handling of reversal edges G.add_edge(node[int(s)], node[int(t)], label=label[2:-2]) return G
def graphml_datatype(val): if val is None: return "string" if is_string_like(val): return "string" if type(val) == type(1): return "int" if type(val) == type(1.0): return "double" if type(val) == type(True): return "boolean" if type(val) == type(1L): return "long"
def parse_pajek(lines): """Parse pajek format graph from string or iterable..""" import shlex if is_string_like(lines): lines=iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G=networkx.XDiGraph(selfloops=True) # are multiedges allowed in Pajek? G.node_attr={} # dictionary to hold node attributes directed=True # assume this is a directed network for now while lines: try: l=lines.next() except: #EOF break if l.startswith("*network"): label,name=l.split() G.name=name if l.startswith("*vertices"): nodelabels={} l,nnodes=l.split() for i in range(int(nnodes)): splitline=shlex.split(lines.next()) id,label,x,y,shape=splitline[0:5] G.add_node(label) nodelabels[id]=label G.node_attr[label]={'id':id,'x':x,'y':y,'shape':shape} extra_attr=zip(splitline[5::2],splitline[6::2]) G.node_attr[label].update(extra_attr) if l.startswith("*edges") or l.startswith("*arcs"): if l.startswith("*edge"): G=networkx.XGraph(G) # switch from digraph to graph for l in lines: splitline=shlex.split(l) ui,vi,w=splitline[0:3] u=nodelabels.get(ui,ui) v=nodelabels.get(vi,vi) edge_data={'value':float(w)} extra_attr=zip(splitline[3::2],splitline[4::2]) edge_data.update(extra_attr) G.add_edge(u,v,edge_data) return G
def parse_pajek(lines): """Parse pajek format graph from string or iterable..""" import shlex if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G = networkx.XDiGraph(selfloops=True) # are multiedges allowed in Pajek? G.node_attr = {} # dictionary to hold node attributes directed = True # assume this is a directed network for now while lines: try: l = lines.next() except: #EOF break if l.startswith("*network"): label, name = l.split() G.name = name if l.startswith("*vertices"): nodelabels = {} l, nnodes = l.split() for i in range(int(nnodes)): splitline = shlex.split(lines.next()) id, label, x, y, shape = splitline[0:5] G.add_node(label) nodelabels[id] = label G.node_attr[label] = {'id': id, 'x': x, 'y': y, 'shape': shape} extra_attr = zip(splitline[5::2], splitline[6::2]) G.node_attr[label].update(extra_attr) if l.startswith("*edges") or l.startswith("*arcs"): if l.startswith("*edge"): G = networkx.XGraph(G) # switch from digraph to graph for l in lines: splitline = shlex.split(l) ui, vi, w = splitline[0:3] u = nodelabels.get(ui, ui) v = nodelabels.get(vi, vi) edge_data = {'value': float(w)} extra_attr = zip(splitline[3::2], splitline[4::2]) edge_data.update(extra_attr) G.add_edge(u, v, edge_data) return G
def parse_leda(lines): """Parse LEDA.GRAPH format from string or iterable. Returns an Graph or DiGraph.""" if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines \ if not (line.startswith('#') or line.startswith('\n') or line=='')]) for i in range(3): lines.next() # Graph du = int(lines.next()) # -1 directed, -2 undirected if du == -1: G = networkx.DiGraph() else: G = networkx.Graph() # Nodes n = int(lines.next()) # number of vertices node = {} for i in range(1, n + 1): # LEDA counts from 1 to n symbol = lines.next()[2:-3] # strip out data from |{data}| if symbol == "": symbol = str(i) # use int if no label - could be trouble node[i] = symbol G.add_nodes_from([s for i, s in node.items()]) # Edges m = int(lines.next()) # number of edges for i in range(m): try: s, t, reversal, label = lines.next().split() except: raise NetworkXError,\ 'Too few fields in LEDA.GRAPH edge %d' % (i+1) # BEWARE: no handling of reversal edges G.add_edge(node[int(s)], node[int(t)], label=label[2:-2]) return G
def parse_leda(lines): """Parse LEDA.GRAPH format from string or iterable. Returns an Graph or DiGraph.""" if is_string_like(lines): lines=iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines \ if not (line.startswith('#') or line.startswith('\n') or line=='')]) for i in range(3): lines.next() # Graph du = int(lines.next()) # -1 directed, -2 undirected if du==-1: G = networkx.DiGraph() else: G = networkx.Graph() # Nodes n =int(lines.next()) # number of vertices node={} for i in range(1,n+1): # LEDA counts from 1 to n symbol=lines.next()[2:-3] # strip out data from |{data}| if symbol=="": symbol=str(i) # use int if no label - could be trouble node[i]=symbol G.add_nodes_from([s for i,s in node.items()]) # Edges m = int(lines.next()) # number of edges for i in range(m): try: s,t,reversal,label=lines.next().split() except: raise NetworkXError,\ 'Too few fields in LEDA.GRAPH edge %d' % (i+1) # BEWARE: no handling of reversal edges G.add_edge(node[int(s)],node[int(t)],label=label[2:-2]) return G
def parse_pajek(lines): """Parse Pajek format graph from string or iterable. Parameters ---------- lines : string or iterable Data in Pajek format. Returns ------- G : NetworkX graph See Also -------- read_pajek() """ import shlex # multigraph=False if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G = nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes while lines: try: l = next(lines) except: #EOF break if l.lower().startswith("*network"): try: label, name = l.split(None, 1) except ValueError: # Line was not of the form: *network NAME pass else: G.graph['name'] = name elif l.lower().startswith("*vertices"): nodelabels = {} l, nnodes = l.split() for i in range(int(nnodes)): l = next(lines) try: splitline = [ x.decode('utf-8') for x in shlex.split(make_str(l).encode('utf-8')) ] except AttributeError: splitline = shlex.split(str(l)) id, label = splitline[0:2] G.add_node(label) nodelabels[id] = label G.node[label] = {'id': id} try: x, y, shape = splitline[2:5] G.node[label].update({ 'x': float(x), 'y': float(y), 'shape': shape }) except: pass extra_attr = zip(splitline[5::2], splitline[6::2]) G.node[label].update(extra_attr) elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"): if l.lower().startswith("*edge"): # switch from multidigraph to multigraph G = nx.MultiGraph(G) if l.lower().startswith("*arcs"): # switch to directed with multiple arcs for each existing edge G = G.to_directed() for l in lines: try: splitline = [ x.decode('utf-8') for x in shlex.split(make_str(l).encode('utf-8')) ] except AttributeError: splitline = shlex.split(str(l)) if len(splitline) < 2: continue ui, vi = splitline[0:2] u = nodelabels.get(ui, ui) v = nodelabels.get(vi, vi) # parse the data attached to this edge and put in a dictionary edge_data = {} try: # there should always be a single value on the edge? w = splitline[2:3] edge_data.update({'weight': float(w[0])}) except: pass # if there isn't, just assign a 1 # edge_data.update({'value':1}) extra_attr = zip(splitline[3::2], splitline[4::2]) edge_data.update(extra_attr) # if G.has_edge(u,v): # multigraph=True G.add_edge(u, v, **edge_data) return G
def parse_pajek(lines,edge_attr=True): """Parse pajek format graph from string or iterable. Primarily used as a helper for read_pajek(). See Also -------- read_pajek() """ import shlex if is_string_like(lines): lines=iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G=nx.MultiDiGraph() # are multiedges allowed in Pajek? directed=True # assume this is a directed network for now while lines: try: l=lines.next() except: #EOF break if l.lower().startswith("*network"): label,name=l.split() G.name=name if l.lower().startswith("*vertices"): nodelabels={} l,nnodes=l.split() for i in range(int(nnodes)): splitline=shlex.split(lines.next()) id,label=splitline[0:2] G.add_node(label) nodelabels[id]=label G.node[label]={'id':id} try: x,y,shape=splitline[2:5] G.node[label].update({'x':x,'y':y,'shape':shape}) except: pass extra_attr=zip(splitline[5::2],splitline[6::2]) G.node[label].update(extra_attr) if l.lower().startswith("*edges") or l.lower().startswith("*arcs"): if l.lower().startswith("*edge"): # switch from digraph to graph G=nx.MultiGraph(G) for l in lines: splitline=shlex.split(l) ui,vi=splitline[0:2] u=nodelabels.get(ui,ui) v=nodelabels.get(vi,vi) # parse the data attached to this edge and # put it in a dictionary edge_data={} try: # there should always be a single value on the edge? w=splitline[2:3] edge_data.update({'weight':float(w[0])}) except: pass # if there isn't, just assign a 1 # edge_data.update({'value':1}) extra_attr=zip(splitline[3::2],splitline[4::2]) edge_data.update(extra_attr) G.add_edge(u,v,**edge_data) return G
def generate_gml(G): """Generate a single entry of the graph G in GML format. Parameters ---------- G : NetworkX graph Returns ------- lines: string Lines in GML format. Notes ----- This implementation does not support all Python data types as GML data. Nodes, node attributes, edge attributes, and graph attributes must be either dictionaries or single stings or numbers. If they are not an attempt is made to represent them as strings. For example, a list as edge data G[1][2]['somedata']=[1,2,3], will be represented in the GML file as:: edge [ source 1 target 2 somedata "[1, 2, 3]" ] """ # recursively make dicts into gml brackets def listify(d, indent, indentlevel): result = '[ \n' for k, v in d.items(): result += (indentlevel+1)*indent + \ string_item(k,v,indentlevel*indent)+'\n' return result + indentlevel * indent + "]" def string_item(k, v, indent): # try to make a string of the data if type(v) == dict: v = listify(v, indent, 2) elif is_string_like(v): v = '"%s"' % v elif type(v) == bool: v = int(v) return "%s %s" % (k, v) # check for attributes or assign empty dict if hasattr(G, 'graph_attr'): graph_attr = G.graph_attr else: graph_attr = {} if hasattr(G, 'node_attr'): node_attr = G.node_attr else: node_attr = {} indent = 2 * ' ' count = iter(range(len(G))) node_id = {} yield "graph [" if G.is_directed(): yield indent + "directed 1" # write graph attributes for k, v in G.graph.items(): if k == 'directed': continue yield indent + string_item(k, v, indent) # write nodes for n in G: yield indent + "node [" # get id or assign number nid = G.node[n].get('id', next(count)) node_id[n] = nid yield 2 * indent + "id %s" % nid label = G.node[n].get('label', n) if is_string_like(label): label = '"%s"' % label yield 2 * indent + 'label %s' % label if n in G: for k, v in G.node[n].items(): if k == 'id' or k == 'label': continue yield 2 * indent + string_item(k, v, indent) yield indent + "]" # write edges for u, v, edgedata in G.edges_iter(data=True): yield indent + "edge [" yield 2 * indent + "source %s" % node_id[u] yield 2 * indent + "target %s" % node_id[v] for k, v in edgedata.items(): if k == 'source': continue if k == 'target': continue yield 2 * indent + string_item(k, v, indent) yield indent + "]" yield "]"
def write_gml(G, path): """ Write the graph G in GML format to the file or file handle path. Examples --------- >>> G=nx.path_graph(4) >>> nx.write_gml(G,"test.gml") path can be a filehandle or a string with the name of the file. >>> fh=open("test.gml",'w') >>> nx.write_gml(G,fh) Filenames ending in .gz or .bz2 will be compressed. >>> nx.write_gml(G,"test.gml.gz") The output file will use the default text encoding on your system. It is possible to write files in other encodings by opening the file with the codecs module. See doc/examples/unicode.py for hints. >>> import codecs >>> fh=codecs.open("test.gml",'w',encoding='iso8859-1')# use iso8859-1 >>> nx.write_gml(G,fh) GML specifications indicate that the file should only use 7bit ASCII text encoding.iso8859-1 (latin-1). Only a single level of attributes for graphs, nodes, and edges, is supported. """ fh=_get_fh(path,mode='w') # comments="#" # pargs=comments+" "+' '.join(sys.argv) # fh.write("%s\n" % (pargs)) # fh.write(comments+" GMT %s\n" % (time.asctime(time.gmtime()))) # fh.write(comments+" %s\n" % (G.name)) # check for attributes or assign empty dict if hasattr(G,'graph_attr'): graph_attr=G.graph_attr else: graph_attr={} if hasattr(G,'node_attr'): node_attr=G.node_attr else: node_attr={} indent=2*' ' count=iter(range(G.number_of_nodes())) node_id={} fh.write("graph [\n") # write graph attributes for k,v in graph_attr.items(): if is_string_like(v): v='"'+v+'"' fh.write(indent+"%s %s\n"%(k,v)) # write nodes for n in G: fh.write(indent+"node [\n") # get id or assign number if n in node_attr: nid=node_attr[n].get('id',count.next()) else: nid=count.next() node_id[n]=nid fh.write(2*indent+"id %s\n"%nid) fh.write(2*indent+"label \"%s\"\n"%n) if n in node_attr: for k,v in node_attr[n].items(): if is_string_like(v): v='"'+v+'"' if k=='id': continue fh.write(2*indent+"%s %s\n"%(k,v)) fh.write(indent+"]\n") # write edges for e in G.edges_iter(): if len(e)==3: u,v,d=e # try to guess what is on the edge and do something reasonable edgedata={} if d is None: # no data pass elif hasattr(d,'iteritems'): # try dict-like edgedata=dict(d.iteritems()) elif hasattr(d,'__iter__'): # some kind of container edgedata['data']=d.__repr__() else: # something else - string, number edgedata['data']=d else: u,v=e edgedata={} fh.write(indent+"edge [\n") fh.write(2*indent+"source %s\n"%node_id[u]) fh.write(2*indent+"target %s\n"%node_id[v]) for k,v in edgedata.items(): if k=='source': continue if k=='target': continue if is_string_like(v): v='"'+v+'"' fh.write(2*indent+"%s %s\n"%(k,v)) fh.write(indent+"]\n") fh.write("]\n")
def parse_pajek_(lines): import shlex import networkx as nx from networkx.utils import is_string_like, open_file, make_str # multigraph=False if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G = nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes labels = [] # in the order of the file, needed for matrix while lines: try: l = next(lines) except: # EOF break if l.lower().startswith("*network"): try: label, name = l.split(None, 1) except ValueError: # Line was not of the form: *network NAME pass else: G.graph['name'] = name elif l.lower().startswith("*vertices"): nodelabels = {} l, nnodes = l.split() for i in range(int(nnodes)): l = next(lines) try: splitline = [ x.decode('utf-8') for x in shlex.split(make_str(l).encode('utf-8')) ] except AttributeError: splitline = shlex.split(str(l)) id, label = splitline[0:2] labels.append(label) G.add_node(label) nodelabels[id] = label G.nodes[label]['id'] = id try: x, y, shape = splitline[2:5] G.nodes[label].update({ 'x': float(x), 'y': float(y), 'shape': shape }) except: pass extra_attr = zip(splitline[5::2], splitline[6::2]) G.nodes[label].update(extra_attr) elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"): if l.lower().startswith("*edge"): # switch from multidigraph to multigraph G = nx.MultiGraph(G) if l.lower().startswith("*arcs"): # switch to directed with multiple arcs for each existing edge G = G.to_directed() for l in lines: try: splitline = [ x.decode('utf-8') for x in shlex.split(make_str(l).encode('utf-8')) ] except AttributeError: splitline = shlex.split(str(l)) if len(splitline) < 2: continue ui, vi = splitline[0:2] u = nodelabels.get(ui, ui) v = nodelabels.get(vi, vi) # parse the data attached to this edge and put in a dictionary edge_data = {} try: # there should always be a single value on the edge? w = splitline[2:3] edge_data.update({'weight': float(w[0])}) except: pass # if there isn't, just assign a 1 # edge_data.update({'value':1}) extra_attr = zip(splitline[3::2], splitline[4::2]) edge_data.update(extra_attr) # if G.has_edge(u,v): # multigraph=True G.add_edge(u, v, **edge_data) elif l.lower().startswith("*matrix"): G = nx.DiGraph(G) adj_list = ((labels[row], labels[col], { 'weight': int(data) }) for (row, line) in enumerate(lines) for (col, data) in enumerate(line.split()) if int(data) != 0) G.add_edges_from(adj_list) return G
def union(G, H, create_using=None, rename=False, name=None): """ Return the union of graphs G and H. Graphs G and H must be disjoint, otherwise an exception is raised. Parameters ---------- G,H : graph A NetworkX graph create_using : NetworkX graph Use specified graph for result. Otherwise a new graph is created. rename : bool (default=False) Node names of G and H can be changed be specifying the tuple rename=('G-','H-') (for example). Node u in G is then renamed "G-u" and v in H is renamed "H-v". name : string Specify name for union graph Notes ----- To force a disjoint union with node relabeling, use disjoint_union(G,H) or convert_node_labels_to integers(). """ if name is None: name = "union( %s, %s )" % (G.name, H.name) if create_using is None: R = G.__class__() else: R = create_using R.clear() R.name = name # rename graph to obtain disjoint node labels # note that for objects w/o succinct __name__, # the new labels can be quite verbose # See also disjoint_union if rename: # create new string labels Gname = {} Hname = {} for v in G: if is_string_like(v): Gname[v] = rename[0] + v else: Gname[v] = rename[0] + repr(v) for v in H: if is_string_like(v): Hname[v] = rename[1] + v else: Hname[v] = rename[1] + repr(v) else: Gname = dict(((v, v) for v in G)) Hname = dict(((v, v) for v in H)) # node name check Hnames = set(Hname.values()) Gnames = set(Gname.values()) if Gnames & Hnames: raise networkx.NetworkXError,\ "node sets of G and H are not disjoint. Use appropriate rename=('Gprefix','Hprefix')" # node names OK, now build union R.add_nodes_from(Gnames) R.add_edges_from( ((Gname[u], Gname[v], x) for u, v, x in G.edges_iter(data=True))) R.add_nodes_from(Hnames) R.add_edges_from( ((Hname[u], Hname[v], x) for u, v, x in H.edges_iter(data=True))) return R
def label(x): if is_string_like(x): name = prefix + x else: name = prefix + repr(x) return name
def test_is_string_like(): assert is_string_like("aaaa") assert not is_string_like(None) assert not is_string_like(123)
def draw_networkx_edge_labels(G, pos, edge_labels=None, label_pos=0.5, font_size=10, font_color='k', font_family='sans-serif', font_weight='normal', alpha=1.0, bbox=None, ax=None, rotate=True, **kwds): """Draw edge labels. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. alpha : float The text transparency (default=1.0) edge_labels : dictionary Edge labels in a dictionary keyed by edge two-tuple of text labels (default=None). Only labels for the keys in the dictionary are drawn. label_pos : float Position of edge label along edge (0=head, 0.5=center, 1=tail) font_size : int Font size for text labels (default=12) font_color : string Font color string (default='k' black) font_weight : string Font weight (default='normal') font_family : string Font family (default='sans-serif') bbox : Matplotlib bbox Specify text box shape and colors. clip_on : bool Turn on clipping at axis boundaries (default=True) Returns ------- dict `dict` of labels keyed on the edges Examples -------- >>> G = nx.dodecahedral_graph() >>> edge_labels = nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G)) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_edges() draw_networkx_labels() """ try: import matplotlib.pyplot as plt import numpy as np except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if edge_labels is None: labels = {(u, v): d for u, v, d in G.edges(data=True)} else: labels = edge_labels text_items = {} for (n1, n2), label in labels.items(): (x1, y1) = pos[n1] (x2, y2) = pos[n2] (x, y) = (x1 * label_pos + x2 * (1.0 - label_pos), y1 * label_pos + y2 * (1.0 - label_pos)) if rotate: # in degrees angle = np.arctan2(y2 - y1, x2 - x1) / (2.0 * np.pi) * 360 # make label orientation "right-side-up" if angle > 90: angle -= 180 if angle < - 90: angle += 180 # transform data coordinate angle to screen coordinate angle xy = np.array((x, y)) trans_angle = ax.transData.transform_angles(np.array((angle,)), xy.reshape((1, 2)))[0] else: trans_angle = 0.0 # use default box of white with white border if bbox is None: bbox = dict(boxstyle='round', ec=(1.0, 1.0, 1.0), fc=(1.0, 1.0, 1.0), ) if not is_string_like(label): label = str(label) # this makes "1" and 1 labeled the same # set optional alignment horizontalalignment = kwds.get('horizontalalignment', 'center') verticalalignment = kwds.get('verticalalignment', 'center') t = ax.text(x, y, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, rotation=trans_angle, transform=ax.transData, bbox=bbox, zorder=1, clip_on=True, ) text_items[(n1, n2)] = t plt.tick_params( axis='both', which='both', bottom=False, left=False, labelbottom=False, labelleft=False) return text_items
def parse_pajek(lines): """Parse pajek format graph from string or iterable..""" import shlex if is_string_like(lines): lines=iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G=networkx.DiGraph() # are multiedges allowed in Pajek? G.node_attr={} # dictionary to hold node attributes directed=True # assume this is a directed network for now while lines: try: l=lines.next() l=l.lower() except: #EOF break if l.startswith("#"): continue if l.startswith("*network"): label,name=l.split() G.name=name if l.startswith("*vertices"): nodelabels={} l,nnodes=l.split() while not l.startswith("*arcs"): if l.startswith('#'): l = lines.next() l = l.lower() continue if l.startswith('*'): l = lines.next() l = l.lower() continue splitline=shlex.split(l) #print splitline id, label = splitline[0:2] G.add_node(label) nodelabels[id]=label G.node_attr[label]={'id':id} if len(splitline) > 2: id,label,x,y=splitline[0:4] G.node_attr[label]={'id':id,'x':x,'y':y} extra_attr=zip(splitline[4::2],splitline[5::2]) #print extra_attr G.node_attr[label].update(extra_attr) l = lines.next() l = l.lower() if l.startswith("*arcs"): for l in lines: if not l: break if l.startswith('#'): continue splitline=shlex.split(l) ui,vi,w=splitline[0:3] u=nodelabels.get(ui,ui) v=nodelabels.get(vi,vi) edge_data={'value':float(w)} extra_attr=zip(splitline[3::2],splitline[4::2]) edge_data.update(extra_attr) if G.has_edge(u,v): if G[u][v]['value'] > float(w): G.add_edge(u,v,**edge_data) else: G.add_edge(u,v,**edge_data) if not G.name: raise Exception("No graph definition found") if len(G.nodes()) == 0: raise Exception("No graph definition found") return G
def draw_networkx_edges(G, pos, edgelist=None, width=1.0, edge_color='k', style='solid', alpha=1.0, arrowstyle='-|>', arrowsize=10, edge_cmap=None, edge_vmin=None, edge_vmax=None, ax=None, arrows=True, label=None, node_size=300, nodelist=None, node_shape="o", connectionstyle=None, **kwds): """Draw the edges of the graph G. This draws only the edges of the graph G. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. edgelist : collection of edge tuples Draw only specified edges(default=G.edges()) width : float, or array of floats Line width of edges (default=1.0) edge_color : color string, or array of floats Edge color. Can be a single color format string (default='r'), or a sequence of colors with the same length as edgelist. If numeric values are specified they will be mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters. style : string Edge line style (default='solid') (solid|dashed|dotted,dashdot) alpha : float The edge transparency (default=1.0) edge_ cmap : Matplotlib colormap Colormap for mapping intensities of edges (default=None) edge_vmin,edge_vmax : floats Minimum and maximum for edge colormap scaling (default=None) ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. arrows : bool, optional (default=True) For directed graphs, if True draw arrowheads. Note: Arrows will be the same color as edges. arrowstyle : str, optional (default='-|>') For directed graphs, choose the style of the arrow heads. See :py:class: `matplotlib.patches.ArrowStyle` for more options. arrowsize : int, optional (default=10) For directed graphs, choose the size of the arrow head head's length and width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute `mutation_scale` for more info. connectionstyle : str, optional (default=None) Pass the connectionstyle parameter to create curved arc of rounding radius rad. For example, connectionstyle='arc3,rad=0.2'. See :py:class: `matplotlib.patches.ConnectionStyle` and :py:class: `matplotlib.patches.FancyArrowPatch` for more info. label : [None| string] Label for legend Returns ------- matplotlib.collection.LineCollection `LineCollection` of the edges list of matplotlib.patches.FancyArrowPatch `FancyArrowPatch` instances of the directed edges Depending whether the drawing includes arrows or not. Notes ----- For directed graphs, arrows are drawn at the head end. Arrows can be turned off with keyword arrows=False. Be sure to include `node_size` as a keyword argument; arrows are drawn considering the size of nodes. Examples -------- >>> G = nx.dodecahedral_graph() >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) >>> G = nx.DiGraph() >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)]) >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) >>> alphas = [0.3, 0.4, 0.5] >>> for i, arc in enumerate(arcs): # change alpha values of arcs ... arc.set_alpha(alphas[i]) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_labels() draw_networkx_edge_labels() """ try: import matplotlib import matplotlib.pyplot as plt import matplotlib.cbook as cb from matplotlib.colors import colorConverter, Colormap, Normalize from matplotlib.collections import LineCollection from matplotlib.patches import FancyArrowPatch import numpy as np except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if edgelist is None: edgelist = list(G.edges()) if not edgelist or len(edgelist) == 0: # no edges! return None if nodelist is None: nodelist = list(G.nodes()) # set edge positions edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist]) if not cb.iterable(width): lw = (width,) else: lw = width if not is_string_like(edge_color) \ and cb.iterable(edge_color) \ and len(edge_color) == len(edge_pos): if np.alltrue([is_string_like(c) for c in edge_color]): # (should check ALL elements) # list of color letters such as ['k','r','k',...] edge_colors = tuple([colorConverter.to_rgba(c, alpha) for c in edge_color]) elif np.alltrue([not is_string_like(c) for c in edge_color]): # If color specs are given as (rgb) or (rgba) tuples, we're OK if np.alltrue([cb.iterable(c) and len(c) in (3, 4) for c in edge_color]): edge_colors = tuple(edge_color) else: # numbers (which are going to be mapped with a colormap) edge_colors = None else: raise ValueError('edge_color must contain color names or numbers') else: if is_string_like(edge_color) or len(edge_color) == 1: edge_colors = (colorConverter.to_rgba(edge_color, alpha), ) else: msg = 'edge_color must be a color or list of one color per edge' raise ValueError(msg) if (not G.is_directed() or not arrows): edge_collection = LineCollection(edge_pos, colors=edge_colors, linewidths=lw, antialiaseds=(1,), linestyle=style, transOffset=ax.transData, ) edge_collection.set_zorder(1) # edges go behind nodes edge_collection.set_label(label) ax.add_collection(edge_collection) # Note: there was a bug in mpl regarding the handling of alpha values # for each line in a LineCollection. It was fixed in matplotlib by # r7184 and r7189 (June 6 2009). We should then not set the alpha # value globally, since the user can instead provide per-edge alphas # now. Only set it globally if provided as a scalar. if isinstance(alpha, Number): edge_collection.set_alpha(alpha) if edge_colors is None: if edge_cmap is not None: assert(isinstance(edge_cmap, Colormap)) edge_collection.set_array(np.asarray(edge_color)) edge_collection.set_cmap(edge_cmap) if edge_vmin is not None or edge_vmax is not None: edge_collection.set_clim(edge_vmin, edge_vmax) else: edge_collection.autoscale() return edge_collection arrow_collection = None if G.is_directed() and arrows: # Note: Waiting for someone to implement arrow to intersection with # marker. Meanwhile, this works well for polygons with more than 4 # sides and circle. def to_marker_edge(marker_size, marker): if marker in "s^>v<d": # `large` markers need extra space return np.sqrt(2 * marker_size) / 2 else: return np.sqrt(marker_size) / 2 # Draw arrows with `matplotlib.patches.FancyarrowPatch` arrow_collection = [] mutation_scale = arrowsize # scale factor of arrow head arrow_colors = edge_colors if arrow_colors is None: if edge_cmap is not None: assert(isinstance(edge_cmap, Colormap)) else: edge_cmap = plt.get_cmap() # default matplotlib colormap if edge_vmin is None: edge_vmin = min(edge_color) if edge_vmax is None: edge_vmax = max(edge_color) color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax) for i, (src, dst) in enumerate(edge_pos): x1, y1 = src x2, y2 = dst arrow_color = None line_width = None shrink_source = 0 # space from source to tail shrink_target = 0 # space from head to target if cb.iterable(node_size): # many node sizes src_node, dst_node = edgelist[i][:2] index_node = nodelist.index(dst_node) marker_size = node_size[index_node] shrink_target = to_marker_edge(marker_size, node_shape) else: shrink_target = to_marker_edge(node_size, node_shape) if arrow_colors is None: arrow_color = edge_cmap(color_normal(edge_color[i])) elif len(arrow_colors) > 1: arrow_color = arrow_colors[i] else: arrow_color = arrow_colors[0] if len(lw) > 1: line_width = lw[i] else: line_width = lw[0] arrow = FancyArrowPatch((x1, y1), (x2, y2), arrowstyle=arrowstyle, shrinkA=shrink_source, shrinkB=shrink_target, mutation_scale=mutation_scale, color=arrow_color, linewidth=line_width, connectionstyle=connectionstyle, zorder=1) # arrows go behind nodes # There seems to be a bug in matplotlib to make collections of # FancyArrowPatch instances. Until fixed, the patches are added # individually to the axes instance. arrow_collection.append(arrow) ax.add_patch(arrow) # update view minx = np.amin(np.ravel(edge_pos[:, :, 0])) maxx = np.amax(np.ravel(edge_pos[:, :, 0])) miny = np.amin(np.ravel(edge_pos[:, :, 1])) maxy = np.amax(np.ravel(edge_pos[:, :, 1])) w = maxx - minx h = maxy - miny padx, pady = 0.05 * w, 0.05 * h corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady) ax.update_datalim(corners) ax.autoscale_view() plt.tick_params( axis='both', which='both', bottom=False, left=False, labelbottom=False, labelleft=False) return arrow_collection
def write_gml(G, path): """ Write the graph G in GML format to the file or file handle path. Examples --------- >>> G=nx.path_graph(4) >>> nx.write_gml(G,"test.gml") path can be a filehandle or a string with the name of the file. >>> fh=open("test.gml",'w') >>> nx.write_gml(G,fh) Filenames ending in .gz or .bz2 will be compressed. >>> nx.write_gml(G,"test.gml.gz") The output file will use the default text encoding on your system. It is possible to write files in other encodings by opening the file with the codecs module. See doc/examples/unicode.py for hints. >>> import codecs >>> fh=codecs.open("test.gml",'w',encoding='iso8859-1')# use iso8859-1 >>> nx.write_gml(G,fh) GML specifications indicate that the file should only use 7bit ASCII text encoding.iso8859-1 (latin-1). Only a single level of attributes for graphs, nodes, and edges, is supported. """ fh = _get_fh(path, mode='w') # comments="#" # pargs=comments+" "+' '.join(sys.argv) # fh.write("%s\n" % (pargs)) # fh.write(comments+" GMT %s\n" % (time.asctime(time.gmtime()))) # fh.write(comments+" %s\n" % (G.name)) # check for attributes or assign empty dict if hasattr(G, 'graph_attr'): graph_attr = G.graph_attr else: graph_attr = {} if hasattr(G, 'node_attr'): node_attr = G.node_attr else: node_attr = {} indent = 2 * ' ' count = iter(range(G.number_of_nodes())) node_id = {} fh.write("graph [\n") # write graph attributes for k, v in graph_attr.items(): if is_string_like(v): v = '"' + v + '"' fh.write(indent + "%s %s\n" % (k, v)) # write nodes for n in G: fh.write(indent + "node [\n") # get id or assign number if n in node_attr: nid = node_attr[n].get('id', count.next()) else: nid = count.next() node_id[n] = nid fh.write(2 * indent + "id %s\n" % nid) fh.write(2 * indent + "label \"%s\"\n" % n) if n in node_attr: for k, v in node_attr[n].items(): if is_string_like(v): v = '"' + v + '"' if k == 'id': continue fh.write(2 * indent + "%s %s\n" % (k, v)) fh.write(indent + "]\n") # write edges for e in G.edges_iter(): if len(e) == 3: u, v, d = e # try to guess what is on the edge and do something reasonable edgedata = {} if d is None: # no data pass elif hasattr(d, 'iteritems'): # try dict-like edgedata = dict(d.iteritems()) elif hasattr(d, '__iter__'): # some kind of container edgedata['data'] = d.__repr__() else: # something else - string, number edgedata['data'] = d else: u, v = e edgedata = {} fh.write(indent + "edge [\n") fh.write(2 * indent + "source %s\n" % node_id[u]) fh.write(2 * indent + "target %s\n" % node_id[v]) for k, v in edgedata.items(): if k == 'source': continue if k == 'target': continue if is_string_like(v): v = '"' + v + '"' fh.write(2 * indent + "%s %s\n" % (k, v)) fh.write(indent + "]\n") fh.write("]\n")
def draw_networkx_edges(G, pos, edgelist=None, width=1.0, edge_color='k', style='solid', alpha=1.0, edge_cmap=None, edge_vmin=None, edge_vmax=None, ax=None, arrows=True, label=None, **kwds): """Draw the edges of the graph G. This draws only the edges of the graph G. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. edgelist : collection of edge tuples Draw only specified edges(default=G.edges()) width : float, or array of floats Line width of edges (default=1.0) edge_color : color string, or array of floats Edge color. Can be a single color format string (default='r'), or a sequence of colors with the same length as edgelist. If numeric values are specified they will be mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters. style : string Edge line style (default='solid') (solid|dashed|dotted,dashdot) alpha : float The edge transparency (default=1.0) edge_ cmap : Matplotlib colormap Colormap for mapping intensities of edges (default=None) edge_vmin,edge_vmax : floats Minimum and maximum for edge colormap scaling (default=None) ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. arrows : bool, optional (default=True) For directed graphs, if True draw arrowheads. label : [None| string] Label for legend Returns ------- matplotlib.collection.LineCollection `LineCollection` of the edges Notes ----- For directed graphs, "arrows" (actually just thicker stubs) are drawn at the head end. Arrows can be turned off with keyword arrows=False. Yes, it is ugly but drawing proper arrows with Matplotlib this way is tricky. Examples -------- >>> G = nx.dodecahedral_graph() >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_labels() draw_networkx_edge_labels() """ try: import matplotlib import matplotlib.pyplot as plt import matplotlib.cbook as cb from matplotlib.colors import colorConverter, Colormap from matplotlib.collections import LineCollection import numpy as np except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if edgelist is None: edgelist = list(G.edges()) if not edgelist or len(edgelist) == 0: # no edges! return None # set edge positions edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist]) if not cb.iterable(width): lw = (width, ) else: lw = width if not is_string_like(edge_color) \ and cb.iterable(edge_color) \ and len(edge_color) == len(edge_pos): if np.alltrue([is_string_like(c) for c in edge_color]): # (should check ALL elements) # list of color letters such as ['k','r','k',...] edge_colors = tuple( [colorConverter.to_rgba(c, alpha) for c in edge_color]) elif np.alltrue([not is_string_like(c) for c in edge_color]): # If color specs are given as (rgb) or (rgba) tuples, we're OK if np.alltrue( [cb.iterable(c) and len(c) in (3, 4) for c in edge_color]): edge_colors = tuple(edge_color) else: # numbers (which are going to be mapped with a colormap) edge_colors = None else: raise ValueError( 'edge_color must consist of either color names or numbers') else: if is_string_like(edge_color) or len(edge_color) == 1: edge_colors = (colorConverter.to_rgba(edge_color, alpha), ) else: raise ValueError( 'edge_color must be a single color or list of exactly m colors where m is the number or edges' ) edge_collection = LineCollection( edge_pos, colors=edge_colors, linewidths=lw, antialiaseds=(1, ), linestyle=style, transOffset=ax.transData, ) edge_collection.set_zorder(1) # edges go behind nodes edge_collection.set_label(label) ax.add_collection(edge_collection) # Note: there was a bug in mpl regarding the handling of alpha values for # each line in a LineCollection. It was fixed in matplotlib in r7184 and # r7189 (June 6 2009). We should then not set the alpha value globally, # since the user can instead provide per-edge alphas now. Only set it # globally if provided as a scalar. if cb.is_numlike(alpha): edge_collection.set_alpha(alpha) if edge_colors is None: if edge_cmap is not None: assert (isinstance(edge_cmap, Colormap)) edge_collection.set_array(np.asarray(edge_color)) edge_collection.set_cmap(edge_cmap) if edge_vmin is not None or edge_vmax is not None: edge_collection.set_clim(edge_vmin, edge_vmax) else: edge_collection.autoscale() arrow_collection = None if G.is_directed() and arrows: # a directed graph hack # draw thick line segments at head end of edge # waiting for someone else to implement arrows that will work arrow_colors = edge_colors a_pos = [] p = 1.0 - 0.25 # make head segment 25 percent of edge length for src, dst in edge_pos: x1, y1 = src x2, y2 = dst dx = x2 - x1 # x offset dy = y2 - y1 # y offset d = np.sqrt(float(dx**2 + dy**2)) # length of edge if d == 0: # source and target at same position continue if dx == 0: # vertical edge xa = x2 ya = dy * p + y1 if dy == 0: # horizontal edge ya = y2 xa = dx * p + x1 else: theta = np.arctan2(dy, dx) xa = p * d * np.cos(theta) + x1 ya = p * d * np.sin(theta) + y1 a_pos.append(((xa, ya), (x2, y2))) arrow_collection = LineCollection( a_pos, colors=arrow_colors, linewidths=[4 * ww for ww in lw], antialiaseds=(1, ), transOffset=ax.transData, ) arrow_collection.set_zorder(1) # edges go behind nodes arrow_collection.set_label(label) ax.add_collection(arrow_collection) # update view minx = np.amin(np.ravel(edge_pos[:, :, 0])) maxx = np.amax(np.ravel(edge_pos[:, :, 0])) miny = np.amin(np.ravel(edge_pos[:, :, 1])) maxy = np.amax(np.ravel(edge_pos[:, :, 1])) w = maxx - minx h = maxy - miny padx, pady = 0.05 * w, 0.05 * h corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady) ax.update_datalim(corners) ax.autoscale_view() # if arrow_collection: return edge_collection
def union(G,H,create_using=None,rename=False,name=None): """ Return the union of graphs G and H. Graphs G and H must be disjoint, otherwise an exception is raised. Parameters ---------- G,H : graph A NetworkX graph create_using : NetworkX graph Use specified graph for result. Otherwise a new graph is created. rename : bool (default=False) Node names of G and H can be changed be specifying the tuple rename=('G-','H-') (for example). Node u in G is then renamed "G-u" and v in H is renamed "H-v". name : string Specify name for union graph Notes ----- To force a disjoint union with node relabeling, use disjoint_union(G,H) or convert_node_labels_to integers(). """ if name is None: name="union( %s, %s )"%(G.name,H.name) if create_using is None: R=G.__class__() else: R=create_using R.clear() R.name=name # rename graph to obtain disjoint node labels # note that for objects w/o succinct __name__, # the new labels can be quite verbose # See also disjoint_union if rename: # create new string labels Gname={} Hname={} for v in G: if is_string_like(v): Gname[v]=rename[0]+v else: Gname[v]=rename[0]+repr(v) for v in H: if is_string_like(v): Hname[v]=rename[1]+v else: Hname[v]=rename[1]+repr(v) else: Gname=dict( ((v,v) for v in G) ) Hname=dict( ((v,v) for v in H) ) # node name check Hnames=set(Hname.values()) Gnames=set(Gname.values()) if Gnames & Hnames: raise networkx.NetworkXError,\ "node sets of G and H are not disjoint. Use appropriate rename=('Gprefix','Hprefix')" # node names OK, now build union R.add_nodes_from(Gnames) R.add_edges_from( ( (Gname[u],Gname[v],x) for u,v,x in G.edges_iter(data=True) )) R.add_nodes_from(Hnames) R.add_edges_from( ( (Hname[u],Hname[v],x) for u,v,x in H.edges_iter(data=True) )) return R
def draw_networkx_labels(G, pos, labels=None, font_size=12, font_color='k', font_family='sans-serif', font_weight='normal', alpha=1.0, bbox=None, ax=None, **kwds): """Draw node labels on the graph G. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. labels : dictionary, optional (default=None) Node labels in a dictionary keyed by node of text labels font_size : int Font size for text labels (default=12) font_color : string Font color string (default='k' black) font_family : string Font family (default='sans-serif') font_weight : string Font weight (default='normal') alpha : float The text transparency (default=1.0) ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. Returns ------- dict `dict` of labels keyed on the nodes Examples -------- >>> G = nx.dodecahedral_graph() >>> labels = nx.draw_networkx_labels(G, pos=nx.spring_layout(G)) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_edges() draw_networkx_edge_labels() """ try: import matplotlib.pyplot as plt import matplotlib.cbook as cb except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if labels is None: labels = dict((n, n) for n in G.nodes()) # set optional alignment horizontalalignment = kwds.get('horizontalalignment', 'center') verticalalignment = kwds.get('verticalalignment', 'center') text_items = {} # there is no text collection so we'll fake one for n, label in labels.items(): (x, y) = pos[n] if not is_string_like(label): label = str(label) # this will cause "1" and 1 to be labeled the same t = ax.text(x, y, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, transform=ax.transData, bbox=bbox, clip_on=True, ) text_items[n] = t return text_items
def generate_gml(G): """Generate a single entry of the graph G in GML format. Parameters ---------- G : NetworkX graph Returns ------- lines: string Lines in GML format. Notes ----- This implementation does not support all Python data types as GML data. Nodes, node attributes, edge attributes, and graph attributes must be either dictionaries or single stings or numbers. If they are not an attempt is made to represent them as strings. For example, a list as edge data G[1][2]['somedata']=[1,2,3], will be represented in the GML file as:: edge [ source 1 target 2 somedata "[1, 2, 3]" ] """ # recursively make dicts into gml brackets dicttype = type({}) def listify(d, indent, indentlevel): result = "[ \n" dicttype = type({}) for k, v in d.items(): if type(v) == dicttype: v = listify(v, indent, indentlevel + 1) result += indentlevel * indent + "%s %s\n" % (k, v) return result + indentlevel * indent + "]" # check for attributes or assign empty dict if hasattr(G, "graph_attr"): graph_attr = G.graph_attr else: graph_attr = {} if hasattr(G, "node_attr"): node_attr = G.node_attr else: node_attr = {} indent = 2 * " " count = iter(range(len(G))) node_id = {} yield "graph [" if G.is_directed(): yield indent + "directed 1" # write graph attributes for k, v in G.graph.items(): if type(v) == dicttype: v = listify(v, indent, 2) elif is_string_like(v): v = '"%s"' % v yield indent + "%s %s" % (k, v) # write nodes for n in G: yield indent + "node [" # get id or assign number nid = G.node[n].get("id", next(count)) node_id[n] = nid yield 2 * indent + "id %s" % nid label = G.node[n].pop("label", n) if is_string_like(label): label = '"%s"' % label yield 2 * indent + "label %s" % label if n in G: for k, v in G.node[n].items(): if k == "id": continue if type(v) == dicttype: v = listify(v, indent, 3) elif is_string_like(v): v = '"%s"' % v yield 2 * indent + "%s %s" % (k, v) yield indent + "]" # write edges for u, v, edgedata in G.edges_iter(data=True): # try to guess what is on the edge and do something reasonable yield indent + "edge [" yield 2 * indent + "source %s" % node_id[u] yield 2 * indent + "target %s" % node_id[v] for k, v in edgedata.items(): if k == "source": continue if k == "target": continue if type(v) == dicttype: v = listify(v, indent, 3) elif is_string_like(v): v = '"%s"' % v yield 2 * indent + "%s %s" % (k, v) yield indent + "]" yield "]"
def draw_networkx_edges(G, pos, edgelist=None, width=1.0, edge_color='k', style='solid', alpha=1.0, arrowstyle='-|>', arrowsize=10, edge_cmap=None, edge_vmin=None, edge_vmax=None, ax=None, arrows=True, label=None, node_size=300, nodelist=None, node_shape="o", **kwds): """Draw the edges of the graph G. This draws only the edges of the graph G. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. edgelist : collection of edge tuples Draw only specified edges(default=G.edges()) width : float, or array of floats Line width of edges (default=1.0) edge_color : color string, or array of floats Edge color. Can be a single color format string (default='r'), or a sequence of colors with the same length as edgelist. If numeric values are specified they will be mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters. style : string Edge line style (default='solid') (solid|dashed|dotted,dashdot) alpha : float The edge transparency (default=1.0) edge_ cmap : Matplotlib colormap Colormap for mapping intensities of edges (default=None) edge_vmin,edge_vmax : floats Minimum and maximum for edge colormap scaling (default=None) ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. arrows : bool, optional (default=True) For directed graphs, if True draw arrowheads. Note: Arrows will be the same color as edges. arrowstyle : str, optional (default='-|>') For directed graphs, choose the style of the arrow heads. See :py:class: `matplotlib.patches.ArrowStyle` for more options. arrowsize : int, optional (default=10) For directed graphs, choose the size of the arrow head head's length and width. See :py:class: `matplotlib.patches.FancyArrowPatch` for attribute `mutation_scale` for more info. label : [None| string] Label for legend Returns ------- matplotlib.collection.LineCollection `LineCollection` of the edges list of matplotlib.patches.FancyArrowPatch `FancyArrowPatch` instances of the directed edges Depending whether the drawing includes arrows or not. Notes ----- For directed graphs, arrows are drawn at the head end. Arrows can be turned off with keyword arrows=False. Be sure to include `node_size' as a keyword argument; arrows are drawn considering the size of nodes. Examples -------- >>> G = nx.dodecahedral_graph() >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) >>> G = nx.DiGraph() >>> G.add_edges_from([(1, 2), (1, 3), (2, 3)]) >>> arcs = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) >>> alphas = [0.3, 0.4, 0.5] >>> for i, arc in enumerate(arcs): # change alpha values of arcs ... arc.set_alpha(alphas[i]) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_labels() draw_networkx_edge_labels() """ try: import matplotlib import matplotlib.pyplot as plt import matplotlib.cbook as cb from matplotlib.colors import colorConverter, Colormap, Normalize from matplotlib.collections import LineCollection from matplotlib.patches import FancyArrowPatch import numpy as np except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if edgelist is None: edgelist = list(G.edges()) if not edgelist or len(edgelist) == 0: # no edges! return None if nodelist is None: nodelist = list(G.nodes()) # set edge positions edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist]) if not cb.iterable(width): lw = (width,) else: lw = width if not is_string_like(edge_color) \ and cb.iterable(edge_color) \ and len(edge_color) == len(edge_pos): if np.alltrue([is_string_like(c) for c in edge_color]): # (should check ALL elements) # list of color letters such as ['k','r','k',...] edge_colors = tuple([colorConverter.to_rgba(c, alpha) for c in edge_color]) elif np.alltrue([not is_string_like(c) for c in edge_color]): # If color specs are given as (rgb) or (rgba) tuples, we're OK if np.alltrue([cb.iterable(c) and len(c) in (3, 4) for c in edge_color]): edge_colors = tuple(edge_color) else: # numbers (which are going to be mapped with a colormap) edge_colors = None else: raise ValueError('edge_color must contain color names or numbers') else: if is_string_like(edge_color) or len(edge_color) == 1: edge_colors = (colorConverter.to_rgba(edge_color, alpha), ) else: msg = 'edge_color must be a color or list of one color per edge' raise ValueError(msg) if (not G.is_directed() or not arrows): edge_collection = LineCollection(edge_pos, colors=edge_colors, linewidths=lw, antialiaseds=(1,), linestyle=style, transOffset=ax.transData, ) edge_collection.set_zorder(1) # edges go behind nodes edge_collection.set_label(label) ax.add_collection(edge_collection) # Note: there was a bug in mpl regarding the handling of alpha values # for each line in a LineCollection. It was fixed in matplotlib by # r7184 and r7189 (June 6 2009). We should then not set the alpha # value globally, since the user can instead provide per-edge alphas # now. Only set it globally if provided as a scalar. if cb.is_numlike(alpha): edge_collection.set_alpha(alpha) if edge_colors is None: if edge_cmap is not None: assert(isinstance(edge_cmap, Colormap)) edge_collection.set_array(np.asarray(edge_color)) edge_collection.set_cmap(edge_cmap) if edge_vmin is not None or edge_vmax is not None: edge_collection.set_clim(edge_vmin, edge_vmax) else: edge_collection.autoscale() return edge_collection arrow_collection = None if G.is_directed() and arrows: # Note: Waiting for someone to implement arrow to intersection with # marker. Meanwhile, this works well for polygons with more than 4 # sides and circle. def to_marker_edge(marker_size, marker): if marker in "s^>v<d": # `large` markers need extra space return np.sqrt(2 * marker_size) / 2 else: return np.sqrt(marker_size) / 2 # Draw arrows with `matplotlib.patches.FancyarrowPatch` arrow_collection = [] mutation_scale = arrowsize # scale factor of arrow head arrow_colors = edge_colors if arrow_colors is None: if edge_cmap is not None: assert(isinstance(edge_cmap, Colormap)) else: edge_cmap = plt.get_cmap() # default matplotlib colormap if edge_vmin is None: edge_vmin = min(edge_color) if edge_vmax is None: edge_vmax = max(edge_color) color_normal = Normalize(vmin=edge_vmin, vmax=edge_vmax) for i, (src, dst) in enumerate(edge_pos): x1, y1 = src x2, y2 = dst arrow_color = None line_width = None shrink_source = 0 # space from source to tail shrink_target = 0 # space from head to target if cb.iterable(node_size): # many node sizes src_node, dst_node = edgelist[i] index_node = nodelist.index(dst_node) marker_size = node_size[index_node] shrink_target = to_marker_edge(marker_size, node_shape) else: shrink_target = to_marker_edge(node_size, node_shape) if arrow_colors is None: arrow_color = edge_cmap(color_normal(edge_color[i])) elif len(arrow_colors) > 1: arrow_color = arrow_colors[i] else: arrow_color = arrow_colors[0] if len(lw) > 1: line_width = lw[i] else: line_width = lw[0] arrow = FancyArrowPatch((x1, y1), (x2, y2), arrowstyle=arrowstyle, shrinkA=shrink_source, shrinkB=shrink_target, mutation_scale=mutation_scale, color=arrow_color, linewidth=line_width, zorder=1) # arrows go behind nodes # There seems to be a bug in matplotlib to make collections of # FancyArrowPatch instances. Until fixed, the patches are added # individually to the axes instance. arrow_collection.append(arrow) ax.add_patch(arrow) # update view minx = np.amin(np.ravel(edge_pos[:, :, 0])) maxx = np.amax(np.ravel(edge_pos[:, :, 0])) miny = np.amin(np.ravel(edge_pos[:, :, 1])) maxy = np.amax(np.ravel(edge_pos[:, :, 1])) w = maxx - minx h = maxy - miny padx, pady = 0.05 * w, 0.05 * h corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady) ax.update_datalim(corners) ax.autoscale_view() return arrow_collection
def generate_pajek(G): """Generate lines in Pajek graph format. Parameters ---------- G : graph A Networkx graph References ---------- See http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/draweps.htm for format information. """ if G.name == '': name = 'NetworkX' else: name = G.name # Apparently many Pajek format readers can't process this line # So we'll leave it out for now. # yield '*network %s'%name # write nodes with attributes yield '*vertices %s' % (G.order()) nodes = list(G) # make dictionary mapping nodes to integers nodenumber = dict(zip(nodes, range(1, len(nodes) + 1))) for n in nodes: # copy node attributes and pop mandatory attributes # to avoid duplication. na = G.nodes.get(n, {}).copy() x = na.pop('x', 0.0) y = na.pop('y', 0.0) id = int(na.pop('id', nodenumber[n])) nodenumber[n] = id shape = na.pop('shape', 'ellipse') s = ' '.join(map(make_qstr, (id, n, x, y, shape))) # only optional attributes are left in na. for k, v in na.items(): if is_string_like(v) and v.strip() != '': s += ' %s %s' % (make_qstr(k), make_qstr(v)) else: warnings.warn('Node attribute %s is not processed. %s.' % (k, 'Empty attribute' if is_string_like(v) else 'Non-string attribute')) yield s # write edges with attributes if G.is_directed(): yield '*arcs' else: yield '*edges' for u, v, edgedata in G.edges(data=True): d = edgedata.copy() value = d.pop('weight', 1.0) # use 1 as default edge value s = ' '.join(map(make_qstr, (nodenumber[u], nodenumber[v], value))) for k, v in d.items(): if is_string_like(v) and v.strip() != '': s += ' %s %s' % (make_qstr(k), make_qstr(v)) else: warnings.warn('Edge attribute %s is not processed. %s.' % (k, 'Empty attribute' if is_string_like(v) else 'Non-string attribute')) yield s
def generate_gml(G): """Generate a single entry of the nxgraph G in GML format. Parameters ---------- G : NetworkX nxgraph Returns ------- lines: string Lines in GML format. Notes ----- This implementation does not support all Python data types as GML data. Nodes, node attributes, edge attributes, and nxgraph attributes must be either dictionaries or single stings or numbers. If they are not an attempt is made to represent them as strings. For example, a list as edge data G[1][2]['somedata']=[1,2,3], will be represented in the GML file as:: edge [ source 1 target 2 somedata "[1, 2, 3]" ] """ # recursively make dicts into gml brackets def listify(d,indent,indentlevel): result='[ \n' for k,v in d.items(): if type(v)==dict: v=listify(v,indent,indentlevel+1) result += (indentlevel+1)*indent + \ string_item(k,v,indentlevel*indent)+'\n' return result+indentlevel*indent+"]" def string_item(k,v,indent): # try to make a string of the data if type(v)==dict: v=listify(v,indent,2) elif is_string_like(v): v='"%s"'%v elif type(v)==bool: v=int(v) return "%s %s"%(k,v) # check for attributes or assign empty dict if hasattr(G,'graph_attr'): graph_attr=G.graph_attr else: graph_attr={} if hasattr(G,'node_attr'): node_attr=G.node_attr else: node_attr={} indent=2*' ' count=iter(range(len(G))) node_id={} yield "nxgraph [" if G.is_directed(): yield indent+"directed 1" # write nxgraph attributes for k,v in G.graph.items(): if k == 'directed': continue yield indent+string_item(k,v,indent) # write nodes for n in G: yield indent+"node [" # get id or assign number nid=G.node[n].get('id',next(count)) node_id[n]=nid yield 2*indent+"id %s"%nid label=G.node[n].get('label',n) if is_string_like(label): label='"%s"'%label yield 2*indent+'label %s'%label if n in G: for k,v in G.node[n].items(): if k=='id' or k == 'label': continue yield 2*indent+string_item(k,v,indent) yield indent+"]" # write edges for u,v,edgedata in G.edges_iter(data=True): yield indent+"edge [" yield 2*indent+"source %s"%node_id[u] yield 2*indent+"target %s"%node_id[v] for k,v in edgedata.items(): if k=='source': continue if k=='target': continue yield 2*indent+string_item(k,v,indent) yield indent+"]" yield "]"
def draw_networkx_edges(G, pos, edgelist=None, width=1.0, edge_color='k', style='solid', alpha=1.0, edge_cmap=None, edge_vmin=None, edge_vmax=None, ax=None, arrows=True, label=None, **kwds): """Draw the edges of the graph G. This draws only the edges of the graph G. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. edgelist : collection of edge tuples Draw only specified edges(default=G.edges()) width : float, or array of floats Line width of edges (default=1.0) edge_color : color string, or array of floats Edge color. Can be a single color format string (default='r'), or a sequence of colors with the same length as edgelist. If numeric values are specified they will be mapped to colors using the edge_cmap and edge_vmin,edge_vmax parameters. style : string Edge line style (default='solid') (solid|dashed|dotted,dashdot) alpha : float The edge transparency (default=1.0) edge_ cmap : Matplotlib colormap Colormap for mapping intensities of edges (default=None) edge_vmin,edge_vmax : floats Minimum and maximum for edge colormap scaling (default=None) ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. arrows : bool, optional (default=True) For directed graphs, if True draw arrowheads. label : [None| string] Label for legend Returns ------- matplotlib.collection.LineCollection `LineCollection` of the edges Notes ----- For directed graphs, "arrows" (actually just thicker stubs) are drawn at the head end. Arrows can be turned off with keyword arrows=False. Yes, it is ugly but drawing proper arrows with Matplotlib this way is tricky. Examples -------- >>> G = nx.dodecahedral_graph() >>> edges = nx.draw_networkx_edges(G, pos=nx.spring_layout(G)) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_labels() draw_networkx_edge_labels() """ try: import matplotlib import matplotlib.pyplot as plt import matplotlib.cbook as cb from matplotlib.colors import colorConverter, Colormap from matplotlib.collections import LineCollection import numpy as np except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if edgelist is None: edgelist = list(G.edges()) if not edgelist or len(edgelist) == 0: # no edges! return None # set edge positions edge_pos = np.asarray([(pos[e[0]], pos[e[1]]) for e in edgelist]) if not cb.iterable(width): lw = (width,) else: lw = width if not is_string_like(edge_color) \ and cb.iterable(edge_color) \ and len(edge_color) == len(edge_pos): if np.alltrue([is_string_like(c) for c in edge_color]): # (should check ALL elements) # list of color letters such as ['k','r','k',...] edge_colors = tuple([colorConverter.to_rgba(c, alpha) for c in edge_color]) elif np.alltrue([not is_string_like(c) for c in edge_color]): # If color specs are given as (rgb) or (rgba) tuples, we're OK if np.alltrue([cb.iterable(c) and len(c) in (3, 4) for c in edge_color]): edge_colors = tuple(edge_color) else: # numbers (which are going to be mapped with a colormap) edge_colors = None else: raise ValueError('edge_color must consist of either color names or numbers') else: if is_string_like(edge_color) or len(edge_color) == 1: edge_colors = (colorConverter.to_rgba(edge_color, alpha), ) else: raise ValueError( 'edge_color must be a single color or list of exactly m colors where m is the number or edges') edge_collection = LineCollection(edge_pos, colors=edge_colors, linewidths=lw, antialiaseds=(1,), linestyle=style, transOffset=ax.transData, ) edge_collection.set_zorder(1) # edges go behind nodes edge_collection.set_label(label) ax.add_collection(edge_collection) # Note: there was a bug in mpl regarding the handling of alpha values for # each line in a LineCollection. It was fixed in matplotlib in r7184 and # r7189 (June 6 2009). We should then not set the alpha value globally, # since the user can instead provide per-edge alphas now. Only set it # globally if provided as a scalar. if cb.is_numlike(alpha): edge_collection.set_alpha(alpha) if edge_colors is None: if edge_cmap is not None: assert(isinstance(edge_cmap, Colormap)) edge_collection.set_array(np.asarray(edge_color)) edge_collection.set_cmap(edge_cmap) if edge_vmin is not None or edge_vmax is not None: edge_collection.set_clim(edge_vmin, edge_vmax) else: edge_collection.autoscale() arrow_collection = None if G.is_directed() and arrows: # a directed graph hack # draw thick line segments at head end of edge # waiting for someone else to implement arrows that will work arrow_colors = edge_colors a_pos = [] p = 1.0 - 0.25 # make head segment 25 percent of edge length for src, dst in edge_pos: x1, y1 = src x2, y2 = dst dx = x2 - x1 # x offset dy = y2 - y1 # y offset d = np.sqrt(float(dx**2 + dy**2)) # length of edge if d == 0: # source and target at same position continue if dx == 0: # vertical edge xa = x2 ya = dy * p + y1 if dy == 0: # horizontal edge ya = y2 xa = dx * p + x1 else: theta = np.arctan2(dy, dx) xa = p * d * np.cos(theta) + x1 ya = p * d * np.sin(theta) + y1 a_pos.append(((xa, ya), (x2, y2))) arrow_collection = LineCollection(a_pos, colors=arrow_colors, linewidths=[4 * ww for ww in lw], antialiaseds=(1,), transOffset=ax.transData, ) arrow_collection.set_zorder(1) # edges go behind nodes ax.add_collection(arrow_collection) # update view minx = np.amin(np.ravel(edge_pos[:, :, 0])) maxx = np.amax(np.ravel(edge_pos[:, :, 0])) miny = np.amin(np.ravel(edge_pos[:, :, 1])) maxy = np.amax(np.ravel(edge_pos[:, :, 1])) w = maxx - minx h = maxy - miny padx, pady = 0.05 * w, 0.05 * h corners = (minx - padx, miny - pady), (maxx + padx, maxy + pady) ax.update_datalim(corners) ax.autoscale_view() # if arrow_collection: return edge_collection
def parse_pajek(lines): """Parse Pajek format graph from string or iterable. Parameters ---------- lines : string or iterable Data in Pajek format. Returns ------- G : NetworkX graph See Also -------- read_pajek() """ import shlex # multigraph=False if is_string_like(lines): lines = iter(lines.split("\n")) lines = iter([line.rstrip("\n") for line in lines]) G = nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes labels = [] # in the order of the file, needed for matrix while lines: try: l = next(lines) except: # EOF break if l.lower().startswith("*network"): try: label, name = l.split(None, 1) except ValueError: # Line was not of the form: *network NAME pass else: G.graph["name"] = name elif l.lower().startswith("*vertices"): nodelabels = {} l, nnodes = l.split() for i in range(int(nnodes)): l = next(lines) try: splitline = [x.decode("utf-8") for x in shlex.split(make_str(l).encode("utf-8"))] except AttributeError: splitline = shlex.split(str(l)) id, label = splitline[0:2] labels.append(label) G.add_node(label) nodelabels[id] = label G.node[label] = {"id": id} try: x, y, shape = splitline[2:5] G.node[label].update({"x": float(x), "y": float(y), "shape": shape}) except: pass extra_attr = zip(splitline[5::2], splitline[6::2]) G.node[label].update(extra_attr) elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"): if l.lower().startswith("*edge"): # switch from multidigraph to multigraph G = nx.MultiGraph(G) if l.lower().startswith("*arcs"): # switch to directed with multiple arcs for each existing edge G = G.to_directed() for l in lines: try: splitline = [x.decode("utf-8") for x in shlex.split(make_str(l).encode("utf-8"))] except AttributeError: splitline = shlex.split(str(l)) if len(splitline) < 2: continue ui, vi = splitline[0:2] u = nodelabels.get(ui, ui) v = nodelabels.get(vi, vi) # parse the data attached to this edge and put in a dictionary edge_data = {} try: # there should always be a single value on the edge? w = splitline[2:3] edge_data.update({"weight": float(w[0])}) except: pass # if there isn't, just assign a 1 # edge_data.update({'value':1}) extra_attr = zip(splitline[3::2], splitline[4::2]) edge_data.update(extra_attr) # if G.has_edge(u,v): # multigraph=True G.add_edge(u, v, **edge_data) elif l.lower().startswith("*matrix"): G = nx.DiGraph(G) adj_list = ( (labels[row], labels[col], {"weight": int(data)}) for (row, line) in enumerate(lines) for (col, data) in enumerate(line.split()) if int(data) != 0 ) G.add_edges_from(adj_list) return G
def draw_networkx_edge_labels(G, pos, edge_labels=None, label_pos=0.5, font_size=10, font_color='k', font_family='sans-serif', font_weight='normal', alpha=1.0, bbox=None, ax=None, rotate=True, **kwds): """Draw edge labels. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. alpha : float The text transparency (default=1.0) edge_labels : dictionary Edge labels in a dictionary keyed by edge two-tuple of text labels (default=None). Only labels for the keys in the dictionary are drawn. label_pos : float Position of edge label along edge (0=head, 0.5=center, 1=tail) font_size : int Font size for text labels (default=12) font_color : string Font color string (default='k' black) font_weight : string Font weight (default='normal') font_family : string Font family (default='sans-serif') bbox : Matplotlib bbox Specify text box shape and colors. clip_on : bool Turn on clipping at axis boundaries (default=True) Returns ------- dict `dict` of labels keyed on the edges Examples -------- >>> G = nx.dodecahedral_graph() >>> edge_labels = nx.draw_networkx_edge_labels(G, pos=nx.spring_layout(G)) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_edges() draw_networkx_labels() """ try: import matplotlib.pyplot as plt import matplotlib.cbook as cb import numpy as np except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if edge_labels is None: labels = {(u, v): d for u, v, d in G.edges(data=True)} else: labels = edge_labels text_items = {} for (n1, n2), label in labels.items(): (x1, y1) = pos[n1] (x2, y2) = pos[n2] (x, y) = (x1 * label_pos + x2 * (1.0 - label_pos), y1 * label_pos + y2 * (1.0 - label_pos)) if rotate: angle = np.arctan2(y2 - y1, x2 - x1) / (2.0 * np.pi) * 360 # degrees # make label orientation "right-side-up" if angle > 90: angle -= 180 if angle < - 90: angle += 180 # transform data coordinate angle to screen coordinate angle xy = np.array((x, y)) trans_angle = ax.transData.transform_angles(np.array((angle,)), xy.reshape((1, 2)))[0] else: trans_angle = 0.0 # use default box of white with white border if bbox is None: bbox = dict(boxstyle='round', ec=(1.0, 1.0, 1.0), fc=(1.0, 1.0, 1.0), ) if not is_string_like(label): label = str(label) # this will cause "1" and 1 to be labeled the same # set optional alignment horizontalalignment = kwds.get('horizontalalignment', 'center') verticalalignment = kwds.get('verticalalignment', 'center') t = ax.text(x, y, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, rotation=trans_angle, transform=ax.transData, bbox=bbox, zorder=1, clip_on=True, ) text_items[(n1, n2)] = t return text_items
def make_str(t): if is_string_like(t): return t return str(t)
def parse_pajek(lines): """Parse Pajek format graph from string or iterable. Parameters ---------- lines : string or iterable Data in Pajek format. Returns ------- G : NetworkX graph See Also -------- read_pajek() """ import shlex # multigraph=False if is_string_like(lines): lines=iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G=nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes while lines: try: l=next(lines) except: #EOF break if l.lower().startswith("*network"): try: label, name = l.split() except ValueError: # Line was not of the form: *network NAME pass else: G.graph['name'] = name elif l.lower().startswith("*vertices"): nodelabels={} l,nnodes=l.split() for i in range(int(nnodes)): splitline=shlex.split(str(next(lines))) id,label=splitline[0:2] G.add_node(label) nodelabels[id]=label G.node[label]={'id':id} try: x,y,shape=splitline[2:5] G.node[label].update({'x':float(x), 'y':float(y), 'shape':shape}) except: pass extra_attr=zip(splitline[5::2],splitline[6::2]) G.node[label].update(extra_attr) elif l.lower().startswith("*edges") or l.lower().startswith("*arcs"): if l.lower().startswith("*edge"): # switch from multidigraph to multigraph G=nx.MultiGraph(G) if l.lower().startswith("*arcs"): # switch to directed with multiple arcs for each existing edge G=G.to_directed() for l in lines: splitline=shlex.split(str(l)) if len(splitline)<2: continue ui,vi=splitline[0:2] u=nodelabels.get(ui,ui) v=nodelabels.get(vi,vi) # parse the data attached to this edge and put in a dictionary edge_data={} try: # there should always be a single value on the edge? w=splitline[2:3] edge_data.update({'weight':float(w[0])}) except: pass # if there isn't, just assign a 1 # edge_data.update({'value':1}) extra_attr=zip(splitline[3::2],splitline[4::2]) edge_data.update(extra_attr) # if G.has_edge(u,v): # multigraph=True G.add_edge(u,v,**edge_data) return G
else: node_attr={} indent=2*' ' count=iter(range(len(G))) node_id={} yield "graph [" if G.is_directed(): yield indent+"directed 1" # write graph attributes for k,v in G.graph.items(): <<<<<<< local if type(v)==dicttype: v=listify(v,indent,2) elif is_string_like(v): v='"%s"'%v elif type(v) == bool: v = int(v) yield indent+"%s %s"%(k,v) ======= yield indent+string_item(k,v,indent) >>>>>>> other # write nodes for n in G: yield indent+"node [" # get id or assign number nid=G.node[n].get('id',next(count)) node_id[n]=nid yield 2*indent+"id %s"%nid label=G.node[n].pop('label',n)
def _open_file(func, *args, **kwargs): # Note that since we have used @decorator, *args, and **kwargs have # already been resolved to match the function signature of func. This # means default values have been propagated. For example, the function # func(x, y, a=1, b=2, **kwargs) if called as func(0,1,b=5,c=10) would # have args=(0,1,1,5) and kwargs={'c':10}. # First we parse the arguments of the decorator. The path_arg could # be an positional argument or a keyword argument. Even if it is try: # path_arg is a required positional argument # This works precisely because we are using @decorator path = args[path_arg] except TypeError: # path_arg is a keyword argument. It is "required" in the sense # that it must exist, according to the decorator specification, # It can exist in `kwargs` by a developer specified default value # or it could have been explicitly set by the user. try: path = kwargs[path_arg] except KeyError: # Could not find the keyword. Thus, no default was specified # in the function signature and the user did not provide it. msg = 'Missing required keyword argument: {0}' raise nx.NetworkXError(msg.format(path_arg)) else: is_kwarg = True except IndexError: # A "required" argument was missing. This can only happen if # the decorator of the function was incorrectly specified. # So this probably is not a user error, but a developer error. msg = "path_arg of open_file decorator is incorrect" raise nx.NetworkXError(msg) else: is_kwarg = False # Now we have the path_arg. There are two types of input to consider: # 1) string representing a path that should be opened # 2) an already opened file object if is_string_like(path): ext = splitext(path)[1] fobj = _dispatch_dict[ext](path, mode=mode) close_fobj = True elif hasattr(path, 'read'): # path is already a file-like object fobj = path close_fobj = False else: # could be None, in which case the algorithm will deal with it fobj = path close_fobj = False # Insert file object into args or kwargs. if is_kwarg: new_args = args kwargs[path_arg] = fobj else: # args is a tuple, so we must convert to list before modifying it. new_args = list(args) new_args[path_arg] = fobj # Finally, we call the original function, making sure to close the fobj. try: result = func(*new_args, **kwargs) finally: if close_fobj: fobj.close() return result
def parse_pajek(lines): """Parse Pajek format graph from string or iterable. Parameters ---------- lines : string or iterable Data in Pajek format. Returns ------- G : NetworkX graph See Also -------- read_pajek() """ import shlex # multigraph=False if is_string_like(lines): lines = iter(lines.split('\n')) lines = iter([line.rstrip('\n') for line in lines]) G = nx.MultiDiGraph() # are multiedges allowed in Pajek? assume yes while lines: try: l = next(lines) except: #EOF break if l.lower().startswith("*network"): label, name = l.split() G.name = name if l.lower().startswith("*vertices"): nodelabels = {} l, nnodes = l.split() for i in range(int(nnodes)): splitline = shlex.split(str(next(lines))) id, label = splitline[0:2] G.add_node(label) nodelabels[id] = label G.node[label] = {'id': id} try: x, y, shape = splitline[2:5] G.node[label].update({ 'x': float(x), 'y': float(y), 'shape': shape }) except: pass extra_attr = zip(splitline[5::2], splitline[6::2]) G.node[label].update(extra_attr) if l.lower().startswith("*edges") or l.lower().startswith("*arcs"): if l.lower().startswith("*edge"): # switch from multi digraph to multi graph G = nx.MultiGraph(G) for l in lines: splitline = shlex.split(str(l)) ui, vi = splitline[0:2] u = nodelabels.get(ui, ui) v = nodelabels.get(vi, vi) # parse the data attached to this edge and put in a dictionary edge_data = {} try: # there should always be a single value on the edge? w = splitline[2:3] edge_data.update({'weight': float(w[0])}) except: pass # if there isn't, just assign a 1 # edge_data.update({'value':1}) extra_attr = zip(splitline[3::2], splitline[4::2]) edge_data.update(extra_attr) # if G.has_edge(u,v): # multigraph=True G.add_edge(u, v, **edge_data) # if not multigraph: # use Graph/DiGraph if no parallel edges # if G.is_directed(): # G=nx.DiGraph(G) # else: # G=nx.Graph(G) return G
def write_gml(G, path): """ Write the graph G in GML format to the file or file handle path. Parameters ---------- path : filename or filehandle The filename or filehandle to write. Filenames ending in .gz or .gz2 will be compressed. See Also -------- read_gml, parse_gml Notes ----- The output file will use the default text encoding on your system. It is possible to write files in other encodings by opening the file with the codecs module. See doc/examples/unicode.py for hints. >>> G=nx.path_graph(4) >>> import codecs >>> fh=codecs.open('test.gml','w',encoding='iso8859-1')# use iso8859-1 >>> nx.write_gml(G,fh) GML specifications indicate that the file should only use 7bit ASCII text encoding.iso8859-1 (latin-1). For nested attributes for graphs, nodes, and edges you should use dicts for the value of the attribute. Examples --------- >>> G=nx.path_graph(4) >>> nx.write_gml(G,"test.gml") path can be a filehandle or a string with the name of the file. >>> fh=open("test.gml",'w') >>> nx.write_gml(G,fh) Filenames ending in .gz or .bz2 will be compressed. >>> nx.write_gml(G,"test.gml.gz") """ fh = _get_fh(path, mode="w") # check for attributes or assign empty dict if hasattr(G, "graph_attr"): graph_attr = G.graph_attr else: graph_attr = {} if hasattr(G, "node_attr"): node_attr = G.node_attr else: node_attr = {} indent = 2 * " " count = iter(range(G.number_of_nodes())) node_id = {} dicttype = type({}) # recursively make dicts into gml brackets def listify(d, indent, indentlevel): result = "[ \n" dicttype = type({}) for k, v in d.iteritems(): if type(v) == dicttype: v = listify(v, indent, indentlevel + 1) result += indentlevel * indent + "%s %s\n" % (k, v) return result + indentlevel * indent + "]" fh.write("graph [\n") if G.is_directed(): fh.write(indent + "directed 1\n") # write graph attributes for k, v in G.graph.items(): if is_string_like(v): v = '"' + v + '"' elif type(v) == dicttype: v = listify(v, indent, 1) fh.write(indent + "%s %s\n" % (k, v)) # write nodes for n in G: fh.write(indent + "node [\n") # get id or assign number nid = G.node[n].get("id", count.next()) node_id[n] = nid fh.write(2 * indent + "id %s\n" % nid) fh.write(2 * indent + 'label "%s"\n' % n) if n in G: for k, v in G.node[n].items(): if is_string_like(v): v = '"' + v + '"' if type(v) == dicttype: v = listify(v, indent, 2) if k == "id": continue fh.write(2 * indent + "%s %s\n" % (k, v)) fh.write(indent + "]\n") # write edges for u, v, edgedata in G.edges_iter(data=True): # try to guess what is on the edge and do something reasonable fh.write(indent + "edge [\n") fh.write(2 * indent + "source %s\n" % node_id[u]) fh.write(2 * indent + "target %s\n" % node_id[v]) for k, v in edgedata.items(): if k == "source": continue if k == "target": continue if is_string_like(v): v = '"' + v + '"' if type(v) == dicttype: v = listify(v, indent, 2) fh.write(2 * indent + "%s %s\n" % (k, v)) fh.write(indent + "]\n") fh.write("]")
def draw_networkx_labels(G, pos, labels=None, font_size=12, font_color='k', font_family='sans-serif', font_weight='normal', alpha=1.0, bbox=None, ax=None, **kwds): """Draw node labels on the graph G. Parameters ---------- G : graph A networkx graph pos : dictionary A dictionary with nodes as keys and positions as values. Positions should be sequences of length 2. labels : dictionary, optional (default=None) Node labels in a dictionary keyed by node of text labels Node-keys in labels should appear as keys in `pos`. If needed use: `{n:lab for n,lab in labels.items() if n in pos}` font_size : int Font size for text labels (default=12) font_color : string Font color string (default='k' black) font_family : string Font family (default='sans-serif') font_weight : string Font weight (default='normal') alpha : float The text transparency (default=1.0) ax : Matplotlib Axes object, optional Draw the graph in the specified Matplotlib axes. Returns ------- dict `dict` of labels keyed on the nodes Examples -------- >>> G = nx.dodecahedral_graph() >>> labels = nx.draw_networkx_labels(G, pos=nx.spring_layout(G)) Also see the NetworkX drawing examples at https://networkx.github.io/documentation/latest/auto_examples/index.html See Also -------- draw() draw_networkx() draw_networkx_nodes() draw_networkx_edges() draw_networkx_edge_labels() """ try: import matplotlib.pyplot as plt import matplotlib.cbook as cb except ImportError: raise ImportError("Matplotlib required for draw()") except RuntimeError: print("Matplotlib unable to open display") raise if ax is None: ax = plt.gca() if labels is None: labels = dict((n, n) for n in G.nodes()) # set optional alignment horizontalalignment = kwds.get('horizontalalignment', 'center') verticalalignment = kwds.get('verticalalignment', 'center') text_items = {} # there is no text collection so we'll fake one for n, label in labels.items(): (x, y) = pos[n] if not is_string_like(label): label = str(label) # this makes "1" and 1 labeled the same t = ax.text(x, y, label, size=font_size, color=font_color, family=font_family, weight=font_weight, alpha=alpha, horizontalalignment=horizontalalignment, verticalalignment=verticalalignment, transform=ax.transData, bbox=bbox, clip_on=True, ) text_items[n] = t plt.tick_params( axis='both', which='both', bottom=False, left=False, labelbottom=False, labelleft=False) return text_items
def draw_edges(G, pos, ax, edgelist=None, width=1.0, width_adjuster=50, edge_color='k', style='solid', alpha=None, edge_cmap=None, edge_vmin=None, edge_vmax=None, traversal_weight=1.0, edge_delengthify=0.15, arrows=True, label=None, zorder=1, **kwds): """ Code cleaned-up version of networkx.draw_networkx_edges New args: width_adjuster - the line width is generated from the weight if present, use this adjuster to thicken the lines (multiply) """ if edgelist is None: edgelist = G.edges() if not edgelist or len(edgelist) == 0: # no edges! return None # set edge positions edge_pos = [(pos[e[0]], pos[e[1]]) for e in edgelist] new_ep = [] for e in edge_pos: x, y = e[0] dx, dy = e[1] # Get edge length elx = (dx - x) * edge_delengthify ely = (dy - y) * edge_delengthify x += elx y += ely dx -= elx dy -= ely new_ep.append(((x, y), (dx, dy))) edge_pos = numpy.asarray(new_ep) if not cb.iterable(width): #print [G.get_edge_data(n[0], n[1])['weight'] for n in edgelist] # see if I can find an edge attribute: if 'weight' in G.get_edge_data(edgelist[0][0], edgelist[0][1]): # Test an edge lw = [ 0.5 + ((G.get_edge_data(n[0], n[1])['weight'] - traversal_weight) * width_adjuster) for n in edgelist ] else: lw = (width, ) else: lw = width if not is_string_like(edge_color) and cb.iterable(edge_color) and len( edge_color) == len(edge_pos): if numpy.alltrue([cb.is_string_like(c) for c in edge_color]): # (should check ALL elements) # list of color letters such as ['k','r','k',...] edge_colors = tuple( [colorConverter.to_rgba(c, alpha) for c in edge_color]) elif numpy.alltrue([not cb.is_string_like(c) for c in edge_color]): # If color specs are given as (rgb) or (rgba) tuples, we're OK if numpy.alltrue( [cb.iterable(c) and len(c) in (3, 4) for c in edge_color]): edge_colors = tuple(edge_color) else: # numbers (which are going to be mapped with a colormap) edge_colors = None else: raise ValueError( 'edge_color must consist of either color names or numbers') else: if is_string_like(edge_color) or len(edge_color) == 1: edge_colors = (colorConverter.to_rgba(edge_color, alpha), ) else: raise ValueError( 'edge_color must be a single color or list of exactly m colors where m is the number or edges' ) edge_collection = LineCollection(edge_pos, colors=edge_colors, linewidths=lw, antialiaseds=(1, ), linestyle=style, transOffset=ax.transData, zorder=zorder) edge_collection.set_label(label) ax.add_collection(edge_collection) if cb.is_numlike(alpha): edge_collection.set_alpha(alpha) if edge_colors is None: if edge_cmap is not None: assert (isinstance(edge_cmap, Colormap)) edge_collection.set_array(numpy.asarray(edge_color)) edge_collection.set_cmap(edge_cmap) if edge_vmin is not None or edge_vmax is not None: edge_collection.set_clim(edge_vmin, edge_vmax) else: edge_collection.autoscale() # update view ''' minx = numpy.amin(numpy.ravel(edge_pos[:,:,0])) maxx = numpy.amax(numpy.ravel(edge_pos[:,:,0])) miny = numpy.amin(numpy.ravel(edge_pos[:,:,1])) maxy = numpy.amax(numpy.ravel(edge_pos[:,:,1])) w = maxx-minx h = maxy-miny padx, pady = 0.05*w, 0.05*h corners = (minx-padx, miny-pady), (maxx+padx, maxy+pady) ax.update_datalim(corners) ax.autoscale_view() ''' return (edge_collection)
def write_gml(G, path): """ Write the graph G in GML format to the file or file handle path. Parameters ---------- path : filename or filehandle The filename or filehandle to write. Filenames ending in .gz or .gz2 will be compressed. See Also -------- read_gml, parse_gml Notes ----- The output file will use the default text encoding on your system. It is possible to write files in other encodings by opening the file with the codecs module. See doc/examples/unicode.py for hints. >>> G=nx.path_graph(4) >>> import codecs >>> fh=codecs.open('test.gml','w',encoding='iso8859-1')# use iso8859-1 >>> nx.write_gml(G,fh) GML specifications indicate that the file should only use 7bit ASCII text encoding.iso8859-1 (latin-1). For nested attributes for graphs, nodes, and edges you should use dicts for the value of the attribute. Examples --------- >>> G=nx.path_graph(4) >>> nx.write_gml(G,"test.gml") path can be a filehandle or a string with the name of the file. >>> fh=open("test.gml",'w') >>> nx.write_gml(G,fh) Filenames ending in .gz or .bz2 will be compressed. >>> nx.write_gml(G,"test.gml.gz") """ fh = _get_fh(path, mode='w') # check for attributes or assign empty dict if hasattr(G, 'graph_attr'): graph_attr = G.graph_attr else: graph_attr = {} if hasattr(G, 'node_attr'): node_attr = G.node_attr else: node_attr = {} indent = 2 * ' ' count = iter(range(G.number_of_nodes())) node_id = {} dicttype = type({}) # recursively make dicts into gml brackets def listify(d, indent, indentlevel): result = '[ \n' dicttype = type({}) for k, v in d.iteritems(): if type(v) == dicttype: v = listify(v, indent, indentlevel + 1) result += indentlevel * indent + "%s %s\n" % (k, v) return result + indentlevel * indent + "]" fh.write("graph [\n") if G.is_directed(): fh.write(indent + "directed 1\n") # write graph attributes for k, v in G.graph.items(): if is_string_like(v): v = '"' + v + '"' elif type(v) == dicttype: v = listify(v, indent, 1) fh.write(indent + "%s %s\n" % (k, v)) # write nodes for n in G: fh.write(indent + "node [\n") # get id or assign number nid = G.node[n].get('id', count.next()) node_id[n] = nid fh.write(2 * indent + "id %s\n" % nid) fh.write(2 * indent + "label \"%s\"\n" % n) if n in G: for k, v in G.node[n].items(): if is_string_like(v): v = '"' + v + '"' if type(v) == dicttype: v = listify(v, indent, 2) if k == 'id': continue fh.write(2 * indent + "%s %s\n" % (k, v)) fh.write(indent + "]\n") # write edges for u, v, edgedata in G.edges_iter(data=True): # try to guess what is on the edge and do something reasonable fh.write(indent + "edge [\n") fh.write(2 * indent + "source %s\n" % node_id[u]) fh.write(2 * indent + "target %s\n" % node_id[v]) for k, v in edgedata.items(): if k == 'source': continue if k == 'target': continue if is_string_like(v): v = '"' + v + '"' if type(v) == dicttype: v = listify(v, indent, 2) fh.write(2 * indent + "%s %s\n" % (k, v)) fh.write(indent + "]\n") fh.write("]")