Ejemplo n.º 1
0
    def add_nodes(self, G, graph_element):
        nodes_element = Element('nodes')
        for node,data in G.nodes_iter(data=True):
            node_data=data.copy()
            # 
            node_id=node_data.pop('id',make_str(node))
            kw={'id':node_id}
            label=node_data.pop('label',make_str(node))
            kw['label']=label

            pid=node_data.pop('pid',False)
            if pid:
                kw['pid']=pid
            if 'start' in node_data:
                kw['start']=make_str(node_data.pop('start'))
            if 'end' in node_data:
                kw['end']=make_str(node_data.pop('end'))
                
            # add node element with attributes                
            node_element = Element("node", **kw)

            # add node element and attr subelements
            default=G.graph.get('node_default',{})
            node_data=self.add_parents(node_element, node_data)
            if self.version=='1.1':
                node_data=self.add_slices(node_element, node_data)
            else:
                node_data=self.add_spells(node_element, node_data)
            node_data=self.add_viz(node_element,node_data)
            node_data=self.add_attributes("node", node_element, 
                                          node_data, default)
            nodes_element.append(node_element)
        graph_element.append(nodes_element)
Ejemplo n.º 2
0
 def add_nodes(self, G, graph_element):
     nodes_element = Element("nodes")
     for node, data in G.nodes(data=True):
         node_data = data.copy()
         node_id = make_str(node_data.pop("id", node))
         kw = {"id": node_id}
         label = make_str(node_data.pop("label", node))
         kw["label"] = label
         try:
             pid = node_data.pop("pid")
             kw["pid"] = make_str(pid)
         except KeyError:
             pass
         # add node element with attributes
         node_element = Element("node", **kw)
         # add node element and attr subelements
         default = G.graph.get("node_default", {})
         node_data = self.add_parents(node_element, node_data)
         if self.version == "1.1":
             node_data = self.add_slices(node_element, node_data)
         else:
             node_data = self.add_spells(node_element, node_data)
         node_data = self.add_viz(node_element, node_data)
         node_data = self.add_attributes("node", node_element, node_data, default)
         nodes_element.append(node_element)
     graph_element.append(nodes_element)
Ejemplo n.º 3
0
    def add_nodes(self, G, graph_element):
        nodes_element = Element("nodes")
        for node, data in G.nodes_iter(data=True):
            node_data = data.copy()
            #
            node_id = node_data.pop("id", make_str(node))
            kw = {"id": node_id}
            label = node_data.pop("label", make_str(node))
            kw["label"] = label

            pid = node_data.pop("pid", False)
            if pid:
                kw["pid"] = pid

            # add node element with attributes
            node_element = Element("node", **kw)

            # add node element and attr subelements
            default = G.graph.get("node_default", {})
            node_data = self.add_parents(node_element, node_data)
            node_data = self.add_slices(node_element, node_data)
            node_data = self.add_viz(node_element, node_data)
            node_data = self.add_attributes("node", node_element, node_data, default)
            nodes_element.append(node_element)
        graph_element.append(nodes_element)
Ejemplo n.º 4
0
 def add_attributes(self, node_or_edge, xml_obj, data, default):
     # Add attrvalues to node or edge
     attvalues = Element("attvalues")
     if len(data) == 0:
         return data
     if "start" in data or "end" in data:
         mode = "dynamic"
     else:
         mode = "static"
     for k, v in list(data.items()):
         # rename generic multigraph key to avoid any name conflict
         if k == "key":
             k = "networkx_key"
         attr_id = self.get_attr_id(make_str(k), self.xml_type[type(v)], node_or_edge, default, mode)
         if type(v) == list:
             # dynamic data
             for val, start, end in v:
                 e = Element("attvalue")
                 e.attrib["for"] = attr_id
                 e.attrib["value"] = make_str(val)
                 e.attrib["start"] = make_str(start)
                 e.attrib["end"] = make_str(end)
                 attvalues.append(e)
         else:
             # static data
             e = Element("attvalue")
             e.attrib["for"] = attr_id
             e.attrib["value"] = make_str(v)
             attvalues.append(e)
     xml_obj.append(attvalues)
     return data
Ejemplo n.º 5
0
    def add_edges(self, G, graph_element):
        def edge_key_data(G):
            # helper function to unify multigraph and graph edge iterator
            if G.is_multigraph():
                for u, v, key, data in G.edges_iter(data=True, keys=True):
                    edge_data = data.copy()
                    edge_data.update(key=key)
                    edge_id = edge_data.pop("id", None)
                    if edge_id is None:
                        edge_id = next(self.edge_id)
                    yield u, v, edge_id, edge_data
            else:
                for u, v, data in G.edges_iter(data=True):
                    edge_data = data.copy()
                    edge_id = edge_data.pop("id", None)
                    if edge_id is None:
                        edge_id = next(self.edge_id)
                    yield u, v, edge_id, edge_data

        edges_element = Element("edges")
        for u, v, key, edge_data in edge_key_data(G):
            kw = {"id": make_str(key)}
            edge_weight = edge_data.pop("weight", False)
            if edge_weight:
                kw["weight"] = make_str(edge_weight)
            edge_type = edge_data.pop("type", False)
            if edge_type:
                kw["type"] = make_str(edge_type)
            edge_element = Element("edge", source=make_str(u), target=make_str(v), **kw)
            default = G.graph.get("edge_default", {})
            edge_data = self.add_viz(edge_element, edge_data)
            edge_data = self.add_attributes("edge", edge_element, edge_data, default)
            edges_element.append(edge_element)
        graph_element.append(edges_element)
Ejemplo n.º 6
0
    def add_graph_element(self, G):
        """
        Serialize graph G in GraphML to the stream.
        """
        if G.is_directed():
            default_edge_type = 'directed'
        else:
            default_edge_type = 'undirected'

        graphid = G.graph.pop('id', None)
        if graphid is None:
            graph_element = self.myElement("graph",
                                           edgedefault=default_edge_type)
        else:
            graph_element = self.myElement("graph",
                                           edgedefault=default_edge_type,
                                           id=graphid)
        default = {}
        data = dict((k, v) for k, v in G.graph.items()
                    if k not in ['node_default', 'edge_default'])
        self.add_attributes("graph", graph_element, data, default)
        self.add_nodes(G, graph_element)
        self.add_edges(G, graph_element)

        # self.attributes contains a mapping from XML Objects to a list of
        # data that needs to be added to them.
        # We postpone processing in order to do type inference/generalization.
        # See self.attr_type
        for (xml_obj, data) in self.attributes.items():
            for (k, v, scope, default) in data:
                xml_obj.append(self.add_data(make_str(k),
                                             self.attr_type(k, scope, v),
                                             make_str(v), scope, default))
        self.xml.append(graph_element)
Ejemplo n.º 7
0
 def add_attributes(self, node_or_edge, xml_obj, data, default):
     # Add attrvalues to node or edge
     attvalues=Element('attvalues')
     if len(data)==0:
         return data
     if 'start' in data or 'end' in data:
         mode='dynamic'
     else:
         mode='static'
     for k,v in data.items():
         # rename generic multigraph key to avoid any name conflict
         if k == 'key':
             k='networkx_key' 
         attr_id = self.get_attr_id(make_str(k), self.xml_type[type(v)],
                                    node_or_edge, default, mode)
         if type(v)==list:
             # dynamic data
             for val,start,end in v:
                 e=Element("attvalue")                
                 e.attrib['for']=attr_id
                 e.attrib['value']=make_str(val)
                 e.attrib['start']=make_str(start)
                 e.attrib['end']=make_str(end)
                 attvalues.append(e)                    
         else:
             # static data
             e=Element("attvalue")
             e.attrib['for']=attr_id
             e.attrib['value']=make_str(v)
             attvalues.append(e)
     xml_obj.append(attvalues)
     return data
Ejemplo n.º 8
0
 def add_attributes(self, scope, xml_obj, data, default):
     """Appends attribute data."""
     for k, v in data.items():
         data_element = self.add_data(make_str(k),
                                      self.attr_type(make_str(k), scope, v),
                                      make_str(v), scope, default.get(k))
         xml_obj.append(data_element)
Ejemplo n.º 9
0
 def add_nodes(self, G, graph_element):
     nodes_element = Element('nodes')
     for node, data in G.nodes(data=True):
         node_data = data.copy()
         node_id = make_str(node_data.pop('id', node))
         kw = {'id': node_id}
         label = make_str(node_data.pop('label', node))
         kw['label'] = label
         try:
             pid = node_data.pop('pid')
             kw['pid'] = make_str(pid)
         except KeyError:
             pass
         # add node element with attributes
         node_element = Element('node', **kw)
         # add node element and attr subelements
         default = G.graph.get('node_default', {})
         node_data = self.add_parents(node_element, node_data)
         if self.version == '1.1':
             node_data = self.add_slices(node_element, node_data)
         else:
             node_data = self.add_spells(node_element, node_data)
         node_data = self.add_viz(node_element, node_data)
         node_data = self.add_attributes('node', node_element,
                                         node_data, default)
         nodes_element.append(node_element)
     graph_element.append(nodes_element)
Ejemplo n.º 10
0
 def add_attributes(self, scope, xml_obj, data, default):
     """Appends attributes to edges or nodes.
     """
     for k, v in data.items():
         default_value = default.get(k)
         obj = self.add_data(make_str(k), type(v), make_str(v), scope=scope, default=default_value)
         xml_obj.append(obj)
Ejemplo n.º 11
0
def to_pydot(N, strict=True):
    """Return a pydot graph from a NetworkX graph N.

    Parameters
    ----------
    N : NetworkX graph
      A graph created with NetworkX

    Examples
    --------
    >>> K5 = nx.complete_graph(5)
    >>> P = nx.nx_pydot.to_pydot(K5)

    Notes
    -----

    """
    import pydotplus
    # set Graphviz graph type
    if N.is_directed():
        graph_type='digraph'
    else:
        graph_type='graph'
    strict=N.number_of_selfloops()==0 and not N.is_multigraph()

    name = N.name
    graph_defaults=N.graph.get('graph',{})
    if name is '':
        P = pydotplus.Dot('', graph_type=graph_type, strict=strict,
                      **graph_defaults)
    else:
        P = pydotplus.Dot('"%s"'%name, graph_type=graph_type, strict=strict,
                      **graph_defaults)
    try:
        P.set_node_defaults(**N.graph['node'])
    except KeyError:
        pass
    try:
        P.set_edge_defaults(**N.graph['edge'])
    except KeyError:
        pass

    for n,nodedata in N.nodes_iter(data=True):
        str_nodedata=dict((k,make_str(v)) for k,v in nodedata.items())
        p=pydotplus.Node(make_str(n),**str_nodedata)
        P.add_node(p)

    if N.is_multigraph():
        for u,v,key,edgedata in N.edges_iter(data=True,keys=True):
            str_edgedata=dict((k,make_str(v)) for k,v in edgedata.items())
            edge=pydotplus.Edge(make_str(u), make_str(v),
                    key=make_str(key), **str_edgedata)
            P.add_edge(edge)

    else:
        for u,v,edgedata in N.edges_iter(data=True):
            str_edgedata=dict((k,make_str(v)) for k,v in edgedata.items())
            edge=pydotplus.Edge(make_str(u),make_str(v),**str_edgedata)
            P.add_edge(edge)
    return P
Ejemplo n.º 12
0
def node_link_graph(data, directed=False, multigraph=True):
    """Return graph from node-link data format.

    Parameters
    ----------
    data : dict
        node-link formatted graph data

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

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

    Returns
    -------
    G : NetworkX graph
       A NetworkX graph object

    Examples
    --------
    >>> from networkx.readwrite import json_graph
    >>> G = nx.Graph([(1,2)])
    >>> data = json_graph.node_link_data(G)
    >>> H = json_graph.node_link_graph(data)

    See Also
    --------
    node_link_data, adjacency_data, tree_data
    """
    multigraph = data.get('multigraph',multigraph)
    directed = data.get('directed',directed)
    if multigraph:
        graph = nx.MultiGraph()
    else:
        graph = nx.Graph()
    if directed:
        graph = graph.to_directed()
    mapping=[]
    graph.graph = dict(data.get('graph',[]))
    c = count()
    for d in data['nodes']:
        node = d.get('id',next(c))
        mapping.append(node)
        nodedata = dict((make_str(k),v) for k,v in d.items() if k!='id')
        graph.add_node(node, **nodedata)
    for d in data['links']:
        link_data = d.copy()
        source = link_data.pop('source')
        target = link_data.pop('target')
        edgedata = dict((make_str(k),v) for k,v in d.items()
                        if k!='source' and k!='target')
        graph.add_edge(mapping[source],mapping[target],**edgedata)
    return graph
Ejemplo n.º 13
0
def _place_initial_states(trs_graph, pd_graph, tikz):
    init_subg = pydot.Subgraph("initial")
    init_subg.set_rank("source")

    for node in trs_graph.states.initial:
        pd_node = pydot.Node(make_str(node))
        init_subg.add_node(pd_node)

        phantom_node = "phantominit" + str(node)
        pd_node = pydot.Node(make_str(phantom_node))
        init_subg.add_node(pd_node)

    pd_graph.add_subgraph(init_subg)
Ejemplo n.º 14
0
 def add_spells(self,node_or_edge_element,node_or_edge_data):
     spells=node_or_edge_data.pop('spells',False)
     if spells:
         spells_element=Element('spells')
         for start,end in spells:
             e=Element('spell')
             if start is not None:
                 e.attrib['start']=make_str(start)
             if end is not None:
                 e.attrib['end']=make_str(end)
             spells_element.append(e)
         node_or_edge_element.append(spells_element)
     return node_or_edge_data
Ejemplo n.º 15
0
def _place_initial_states(trs_graph, pd_graph, tikz):
    init_subg = pydot.Subgraph('initial')
    init_subg.set_rank('source')

    for node in trs_graph.states.initial:
        pd_node = pydot.Node(make_str(node))
        init_subg.add_node(pd_node)

        phantom_node = 'phantominit' + str(node)
        pd_node = pydot.Node(make_str(phantom_node))
        init_subg.add_node(pd_node)

    pd_graph.add_subgraph(init_subg)
Ejemplo n.º 16
0
 def add_edges(self, G, graph_element):
     if G.is_multigraph():
         for u, v, key, data in G.edges_iter(data=True, keys=True):
             edge_element = Element("edge", source=make_str(u), target=make_str(v))
             default = G.graph.get("edge_default", {})
             self.add_attributes("edge", edge_element, data, default)
             self.add_attributes("edge", edge_element, {"key": key}, default)
             graph_element.append(edge_element)
     else:
         for u, v, data in G.edges_iter(data=True):
             edge_element = Element("edge", source=make_str(u), target=make_str(v))
             default = G.graph.get("edge_default", {})
             self.add_attributes("edge", edge_element, data, default)
             graph_element.append(edge_element)
Ejemplo n.º 17
0
 def add_spells(self, node_or_edge_element, node_or_edge_data):
     spells = node_or_edge_data.pop("spells", False)
     if spells:
         spells_element = Element("spells")
         for start, end in spells:
             e = Element("spell")
             if start is not None:
                 e.attrib["start"] = make_str(start)
                 self.alter_graph_mode_timeformat(start)
             if end is not None:
                 e.attrib["end"] = make_str(end)
                 self.alter_graph_mode_timeformat(end)
             spells_element.append(e)
         node_or_edge_element.append(spells_element)
     return node_or_edge_data
Ejemplo n.º 18
0
def generate_adjlist(G, delimiter=' '):
    """Generate a single line of the graph G in adjacency list format.

    Parameters
    ----------
    G : NetworkX graph

    delimiter : string, optional
       Separator for node labels

    Returns
    -------
    lines : string
        Lines of data in adjlist format.

    Examples
    --------
    >>> G = nx.lollipop_graph(4, 3)
    >>> for line in nx.generate_adjlist(G):
    ...     print(line)
    0 1 2 3
    1 2 3
    2 3
    3 4
    4 5
    5 6
    6

    See Also
    --------
    write_adjlist, read_adjlist

    """
    directed = G.is_directed()
    seen = set()
    for s, nbrs in G.adjacency_iter():
        line = make_str(s) + delimiter
        for t, data in nbrs.items():
            if not directed and t in seen:
                continue
            if G.is_multigraph():
                for d in data.values():
                    line += make_str(t) + delimiter
            else:
                line += make_str(t) + delimiter
        if not directed:
            seen.add(s)
        yield line[:-len(delimiter)]
Ejemplo n.º 19
0
 def add_attributes(self, scope, xml_obj, data, default):
     """Appends attribute data to edges or nodes, and stores type information
     to be added later. See add_graph_element.
     """
     for k, v in data.items():
         self.attribute_types[(make_str(k), scope)].add(type(v))
         self.attributes[xml_obj].append([k, v, scope, default.get(k)])
Ejemplo n.º 20
0
 def get_attr_id(self, title, attr_type, edge_or_node, default, mode):
     # find the id of the attribute or generate a new id
     try:
         return self.attr[edge_or_node][mode][title]
     except KeyError:
         # generate new id
         new_id = str(next(self.attr_id))
         self.attr[edge_or_node][mode][title] = new_id
         attr_kwargs = {'id': new_id, 'title': title, 'type': attr_type}
         attribute = Element('attribute', **attr_kwargs)
         # add subelement for data default value if present
         default_title = default.get(title)
         if default_title is not None:
             default_element = Element('default')
             default_element.text = make_str(default_title)
             attribute.append(default_element)
         # new insert it into the XML
         attributes_element = None
         for a in self.graph_element.findall('attributes'):
             # find existing attributes element by class and mode
             a_class = a.get('class')
             a_mode = a.get('mode', 'static') # default mode is static
             if a_class == edge_or_node and a_mode == mode:
                 attributes_element = a
         if attributes_element is None:
             # create new attributes element
             attr_kwargs = {'mode': mode, 'class': edge_or_node}
             attributes_element = Element('attributes', **attr_kwargs)
             self.graph_element.insert(0, attributes_element)
         attributes_element.append(attribute)
     return new_id
Ejemplo n.º 21
0
def pydot_layout(G,prog='neato',root=None, **kwds):
    """Create node positions using Pydot and Graphviz.

    Returns a dictionary of positions keyed by node.

    Examples
    --------
    >>> G=nx.complete_graph(4)
    >>> pos=nx.pydot_layout(G)
    >>> pos=nx.pydot_layout(G,prog='dot')
    
    """
    try:
        import pydot
    except ImportError:
        raise ImportError('pydot_layout() requires pydot ',
                          'http://code.google.com/p/pydot/')

    P=to_pydot(G)
    if root is not None :
        P.set("root",make_str(root))

    D=P.create_dot(prog=prog)

    if D=="":  # no data returned
        print("Graphviz layout with %s failed"%(prog))
        print()
        print("To debug what happened try:")
        print("P=pydot_from_networkx(G)")
        print("P.write_dot(\"file.dot\")")
        print("And then run %s on file.dot"%(prog))
        return

    Q=pydot.graph_from_dot_data(D)

    node_pos={}
    for n in G.nodes():
        pydot_node = pydot.Node(make_str(n)).get_name().encode('utf-8')
        node=Q.get_node(pydot_node)

        if isinstance(node,list):
            node=node[0]
        pos=node.get_pos()[1:-1] # strip leading and trailing double quotes
        if pos != None:
            xx,yy=pos.split(",")
            node_pos[n]=(float(xx),float(yy))
    return node_pos
Ejemplo n.º 22
0
    def add_edges(self, G, graph_element):
        def edge_key_data(G):
            # helper function to unify multigraph and graph edge iterator
            if G.is_multigraph():
                for u,v,key,data in G.edges_iter(data=True,keys=True):
                    edge_data=data.copy()
                    edge_data.update(key=key)
                    edge_id=edge_data.pop('id',None)
                    if edge_id is None:
                        edge_id=next(self.edge_id)
                    yield u,v,edge_id,edge_data
            else:
                for u,v,data in G.edges_iter(data=True):
                    edge_data=data.copy()
                    edge_id=edge_data.pop('id',None)
                    if edge_id is None:
                        edge_id=next(self.edge_id)
                    yield u,v,edge_id,edge_data

        edges_element = Element('edges')
        for u,v,key,edge_data in edge_key_data(G):
            kw={'id':make_str(key)}
            try:
                edge_weight=edge_data.pop('weight')
                kw['weight']=make_str(edge_weight)
            except KeyError:
                pass
            try:
                edge_type=edge_data.pop('type')
                kw['type']=make_str(edge_type)
            except KeyError:
                pass
            source_id = make_str(G.node[u].get('id', u))
            target_id = make_str(G.node[v].get('id', v))
            edge_element = Element("edge",
                                   source=source_id,target=target_id,
                                   **kw)
            default=G.graph.get('edge_default',{})
            if self.version == '1.1':
                edge_data=self.add_slices(edge_element, edge_data)
            else:
                edge_data=self.add_spells(edge_element, edge_data)
            edge_data=self.add_viz(edge_element,edge_data)
            edge_data=self.add_attributes("edge", edge_element,
                                          edge_data, default)
            edges_element.append(edge_element)
        graph_element.append(edges_element)
Ejemplo n.º 23
0
 def add_children(parent, children):
     for data in children:
         child = data['id']
         graph.add_edge(parent, child)
         grandchildren = data.get('children',[])
         if grandchildren:
             add_children(child,grandchildren)
         nodedata = dict((make_str(k),v) for k,v in data.items() 
                         if k!='id' and k!='children')
         graph.add_node(child,attr_dict=nodedata)
Ejemplo n.º 24
0
 def add_children(parent, children_):
     for data in children_:
         child = data[id_]
         graph.add_edge(parent, child)
         grandchildren = data.get(children, [])
         if grandchildren:
             add_children(child, grandchildren)
         nodedata = dict((make_str(k), v) for k, v in data.items()
                         if k != id_ and k != children)
         graph.add_node(child, **nodedata)
Ejemplo n.º 25
0
def tree_graph(data, attrs=_attrs):
    """Return graph from tree data format.

    Parameters
    ----------
    data : dict
        Tree formatted graph data

    Returns
    -------
    G : NetworkX DiGraph

    attrs : dict
        A dictionary that contains two keys 'id' and 'children'. The
        corresponding values provide the attribute names for storing
        NetworkX-internal graph data. The values should be unique. Default
        value: :samp:`dict(id='id', children='children')`.

    Examples
    --------
    >>> from networkx.readwrite import json_graph
    >>> G = nx.DiGraph([(1,2)])
    >>> data = json_graph.tree_data(G,root=1)
    >>> H = json_graph.tree_graph(data)

    Notes
    -----
    The default value of attrs will be changed in a future release of NetworkX.

    See Also
    --------
    tree_graph, node_link_data, adjacency_data
    """
    graph = nx.DiGraph()
    id_ = attrs['id']
    children = attrs['children']

    def add_children(parent, children_):
        for data in children_:
            child = data[id_]
            graph.add_edge(parent, child)
            grandchildren = data.get(children, [])
            if grandchildren:
                add_children(child, grandchildren)
            nodedata = dict((make_str(k), v) for k, v in data.items()
                            if k != id_ and k != children)
            graph.add_node(child, **nodedata)

    root = data[id_]
    children_ = data.get(children, [])
    nodedata = dict((make_str(k), v) for k, v in data.items()
                    if k != id_ and k != children)
    graph.add_node(root, **nodedata)
    add_children(root, children_)
    return graph
Ejemplo n.º 26
0
 def add_data(self, name, element_type, value, scope="all", default=None):
     """
     Make a data element for an edge or a node. Keep a log of the
     type in the keys table.
     """
     if element_type not in self.xml_type:
         raise nx.NetworkXError("GraphML writer does not support " "%s as data values." % element_type)
     key_id = self.get_key(name, self.xml_type[element_type], scope, default)
     data_element = Element("data", key=key_id)
     data_element.text = make_str(value)
     return data_element
Ejemplo n.º 27
0
    def add_edges(self, G, graph_element):
        def edge_key_data(G):
            # helper function to unify multigraph and graph edge iterator
            if G.is_multigraph():
                for u, v, data, key in G.edges(data=True, keys=True):
                    edge_data = data.copy()
                    edge_data.update(key=key)
                    edge_id = edge_data.pop("id", None)
                    if edge_id is None:
                        edge_id = next(self.edge_id)
                    yield u, v, edge_id, edge_data
            else:
                for u, v, data in G.edges(data=True):
                    edge_data = data.copy()
                    edge_id = edge_data.pop("id", None)
                    if edge_id is None:
                        edge_id = next(self.edge_id)
                    yield u, v, edge_id, edge_data

        edges_element = Element("edges")
        for u, v, key, edge_data in edge_key_data(G):
            kw = {"id": make_str(key)}
            try:
                edge_weight = edge_data.pop("weight")
                kw["weight"] = make_str(edge_weight)
            except KeyError:
                pass
            try:
                edge_type = edge_data.pop("type")
                kw["type"] = make_str(edge_type)
            except KeyError:
                pass
            try:
                start = edge_data.pop("start")
                kw["start"] = make_str(start)
                self.alter_graph_mode_timeformat(start)
            except KeyError:
                pass
            try:
                end = edge_data.pop("end")
                kw["end"] = make_str(end)
                self.alter_graph_mode_timeformat(end)
            except KeyError:
                pass
            source_id = make_str(G.node[u].get("id", u))
            target_id = make_str(G.node[v].get("id", v))
            edge_element = Element("edge", source=source_id, target=target_id, **kw)
            default = G.graph.get("edge_default", {})
            if self.version == "1.1":
                edge_data = self.add_slices(edge_element, edge_data)
            else:
                edge_data = self.add_spells(edge_element, edge_data)
            edge_data = self.add_viz(edge_element, edge_data)
            edge_data = self.add_attributes("edge", edge_element, edge_data, default)
            edges_element.append(edge_element)
        graph_element.append(edges_element)
Ejemplo n.º 28
0
 def edge_key_data(G):
     # helper function to unify multigraph and graph edge iterator
     if G.is_multigraph():
         for u, v, key, data in G.edges(data=True, keys=True):
             edge_data = data.copy()
             edge_data.update(key=key)
             edge_id = edge_data.pop('id', None)
             if edge_id is None:
                 edge_id = next(self.edge_id)
                 while make_str(edge_id) in self.all_edge_ids:
                     edge_id = next(self.edge_id)
                 self.all_edge_ids.add(make_str(edge_id))
             yield u, v, edge_id, edge_data
     else:
         for u, v, data in G.edges(data=True):
             edge_data = data.copy()
             edge_id = edge_data.pop('id', None)
             if edge_id is None:
                 edge_id = next(self.edge_id)
                 while make_str(edge_id) in self.all_edge_ids:
                     edge_id = next(self.edge_id)
                 self.all_edge_ids.add(make_str(edge_id))
             yield u, v, edge_id, edge_data
Ejemplo n.º 29
0
 def get_key(self, name, attr_type, scope, default):
     keys_key = (name, attr_type, scope)
     try:
         return self.keys[keys_key]
     except KeyError:
         new_id = "d%i" % len(list(self.keys))
         self.keys[keys_key] = new_id
         key_kwargs = {"id": new_id, "for": scope, "attr.name": name, "attr.type": attr_type}
         key_element = Element("key", **key_kwargs)
         # add subelement for data default value if present
         if default is not None:
             default_element = Element("default")
             default_element.text = make_str(default)
             key_element.append(default_element)
         self.xml.insert(0, key_element)
     return new_id
Ejemplo n.º 30
0
 def add_attributes(self, node_or_edge, xml_obj, data, default):
     # Add attrvalues to node or edge
     attvalues = Element('attvalues')
     if len(data) == 0:
         return data
     mode = 'static'
     for k, v in data.items():
         # rename generic multigraph key to avoid any name conflict
         if k == 'key':
             k = 'networkx_key'
         val_type = type(v)
         if val_type not in self.xml_type:
             raise TypeError('attribute value type is not allowed: %s' % val_type)
         if isinstance(v, list):
             # dynamic data
             for val, start, end in v:
                 val_type = type(val)
                 if start is not None or end is not None:
                     mode = 'dynamic'
                     self.alter_graph_mode_timeformat(start)
                     self.alter_graph_mode_timeformat(end)
                     break
             attr_id = self.get_attr_id(make_str(k), self.xml_type[val_type],
                                        node_or_edge, default, mode)
             for val, start, end in v:
                 e = Element('attvalue')
                 e.attrib['for'] = attr_id
                 e.attrib['value'] = make_str(val)
                 if start is not None:
                     e.attrib['start'] = make_str(start)
                 if end is not None:
                     e.attrib['end'] = make_str(end)
                 attvalues.append(e)
         else:
             # static data
             mode = 'static'
             attr_id = self.get_attr_id(make_str(k), self.xml_type[val_type],
                                        node_or_edge, default, mode)
             e = Element('attvalue')
             e.attrib['for'] = attr_id
             if isinstance(v, bool):
                 e.attrib['value'] = make_str(v).lower()
             else:
                 e.attrib['value'] = make_str(v)
             attvalues.append(e)
     xml_obj.append(attvalues)
     return data
Ejemplo n.º 31
0
 def add_attributes(self, node_or_edge, xml_obj, data, default):
     # Add attrvalues to node or edge
     attvalues = Element('attvalues')
     if len(data) == 0:
         return data
     mode = 'static'
     for k, v in data.items():
         # rename generic multigraph key to avoid any name conflict
         if k == 'key':
             k = 'networkx_key'
         val_type = type(v)
         if val_type not in self.xml_type:
             raise TypeError('attribute value type is not allowed: %s'
                             % val_type)
         if isinstance(v, list):
             # dynamic data
             for val, start, end in v:
                 val_type = type(val)
                 if start is not None or end is not None:
                     mode = 'dynamic'
                     self.alter_graph_mode_timeformat(start)
                     self.alter_graph_mode_timeformat(end)
                     break
             attr_id = self.get_attr_id(make_str(k),
                                        self.xml_type[val_type],
                                        node_or_edge, default, mode)
             for val, start, end in v:
                 e = Element('attvalue')
                 e.attrib['for'] = attr_id
                 e.attrib['value'] = make_str(val)
                 # Handle nan, inf, -inf differently
                 if val_type == float:
                     if e.attrib['value'] == 'inf':
                         e.attrib['value'] = 'INF'
                     elif e.attrib['value'] == 'nan':
                         e.attrib['value'] = 'NaN'
                     elif e.attrib['value'] == '-inf':
                         e.attrib['value'] = '-INF'
                 if start is not None:
                     e.attrib['start'] = make_str(start)
                 if end is not None:
                     e.attrib['end'] = make_str(end)
                 attvalues.append(e)
         else:
             # static data
             mode = 'static'
             attr_id = self.get_attr_id(make_str(k),
                                        self.xml_type[val_type],
                                        node_or_edge, default, mode)
             e = Element('attvalue')
             e.attrib['for'] = attr_id
             if isinstance(v, bool):
                 e.attrib['value'] = make_str(v).lower()
             else:
                 e.attrib['value'] = make_str(v)
                 # Handle float nan, inf, -inf differently
                 if val_type == float:
                     if e.attrib['value'] == 'inf':
                         e.attrib['value'] = 'INF'
                     elif e.attrib['value'] == 'nan':
                         e.attrib['value'] = 'NaN'
                     elif e.attrib['value'] == '-inf':
                         e.attrib['value'] = '-INF'
             attvalues.append(e)
     xml_obj.append(attvalues)
     return data
Ejemplo n.º 32
0
def pydot_layout(G, prog='neato', root=None, **kwds):
    """Create node positions using :mod:`pydot` and Graphviz.

    Parameters
    --------
    G : Graph
        NetworkX graph to be laid out.
    prog : optional[str]
        Basename of the GraphViz command with which to layout this graph.
        Defaults to `neato`, the default GraphViz command for undirected graphs.

    Returns
    --------
    dict
        Dictionary of positions keyed by node.

    Examples
    --------
    >>> G = nx.complete_graph(4)
    >>> pos = nx.nx_pydot.pydot_layout(G)
    >>> pos = nx.nx_pydot.pydot_layout(G, prog='dot')
    """
    pydot = _import_pydot()
    P = to_pydot(G)
    if root is not None:
        P.set("root", make_str(root))

    # List of low-level bytes comprising a string in the dot language converted
    # from the passed graph with the passed external GraphViz command.
    D_bytes = P.create_dot(prog=prog)

    # Unique string decoded from these bytes with the preferred locale encoding.
    D = unicode(D_bytes, encoding=getpreferredencoding())

    if D == "":  # no data returned
        print("Graphviz layout with %s failed" % (prog))
        print()
        print("To debug what happened try:")
        print("P = nx.nx_pydot.to_pydot(G)")
        print("P.write_dot(\"file.dot\")")
        print("And then run %s on file.dot" % (prog))
        return

    # List of one or more "pydot.Dot" instances deserialized from this string.
    Q_list = pydot.graph_from_dot_data(D)
    assert len(Q_list) == 1

    # The first and only such instance, as guaranteed by the above assertion.
    Q = Q_list[0]

    node_pos = {}
    for n in G.nodes():
        pydot_node = pydot.Node(make_str(n)).get_name()
        node = Q.get_node(pydot_node)

        if isinstance(node, list):
            node = node[0]
        pos = node.get_pos()[1:-1]  # strip leading and trailing double quotes
        if pos is not None:
            xx, yy = pos.split(",")
            node_pos[n] = (float(xx), float(yy))
    return node_pos
Ejemplo n.º 33
0
def node_link_graph(data, directed=False, multigraph=True, attrs=_attrs):
    """Return graph from node-link data format.

    Parameters
    ----------
    data : dict
        node-link formatted graph data

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

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

    attrs : dict
        A dictionary that contains four keys 'id', 'source', 'target' and
        'key'. The corresponding values provide the attribute names for storing
        NetworkX-internal graph data. Default value:
        :samp:`dict(id='id', source='source', target='target', key='key')`.

    Returns
    -------
    G : NetworkX graph
       A NetworkX graph object

    Examples
    --------
    >>> from networkx.readwrite import json_graph
    >>> G = nx.Graph([(1,2)])
    >>> data = json_graph.node_link_data(G)
    >>> H = json_graph.node_link_graph(data)

    Notes
    -----
    The default value of attrs will be changed in a future release of NetworkX.


    See Also
    --------
    node_link_data, adjacency_data, tree_data
    """
    multigraph = data.get('multigraph', multigraph)
    directed = data.get('directed', directed)
    if multigraph:
        graph = nx.MultiGraph()
    else:
        graph = nx.Graph()
    if directed:
        graph = graph.to_directed()
    id_ = attrs['id']
    source = attrs['source']
    target = attrs['target']
    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
    key = None if not multigraph else attrs['key']
    mapping = []
    graph.graph = data.get('graph', {})
    c = count()
    for d in data['nodes']:
        node = d.get(id_, next(c))
        mapping.append(node)
        nodedata = dict((make_str(k), v) for k, v in d.items() if k != id_)
        graph.add_node(node, **nodedata)
    for d in data['links']:
        src = d[source]
        tgt = d[target]
        if not multigraph:
            edgedata = dict((make_str(k), v) for k, v in d.items()
                            if k != source and k != target)
            graph.add_edge(mapping[src], mapping[tgt], **edgedata)
        else:
            ky = d.get(key, None)
            edgedata = dict((make_str(k), v) for k, v in d.items()
                            if k != source and k != target and k != key)
            graph.add_edge(mapping[src], mapping[tgt], ky, **edgedata)
    return graph
Ejemplo n.º 34
0
def generate_multiline_adjlist(G, delimiter = ' '):
    """Generate a single line of the graph G in multiline adjacency list format.

    Parameters
    ----------
    G : NetworkX graph
    
    delimiter : string, optional
       Separator for node labels 

    Returns
    -------
    lines : string
        Lines of data in multiline adjlist format.

    Examples
    --------
    >>> G = nx.lollipop_graph(4, 3)
    >>> for line in nx.generate_multiline_adjlist(G):
    ...     print(line)    
    0 3
    1 {}
    2 {}
    3 {}
    1 2
    2 {}
    3 {}
    2 1
    3 {}
    3 1
    4 {}
    4 1
    5 {}
    5 1
    6 {}
    6 0

    See Also
    --------
    write_multiline_adjlist, read_multiline_adjlist
    """
    if G.is_directed():
        if G.is_multigraph():
            for s,nbrs in G.adjacency_iter():
                nbr_edges=[ (u,data) 
                            for u,datadict in nbrs.items() 
                            for key,data in datadict.items()]
                deg=len(nbr_edges)
                yield make_str(s)+delimiter+"%i"%(deg)
                for u,d in nbr_edges:
                    if d is None:
                        yield make_str(u)
                    else:
                        yield make_str(u)+delimiter+make_str(d)
        else: # directed single edges
            for s,nbrs in G.adjacency_iter():
                deg=len(nbrs)
                yield make_str(s)+delimiter+"%i"%(deg)
                for u,d in nbrs.items():
                   if d is None:    
                       yield make_str(u)
                   else:   
                       yield make_str(u)+delimiter+make_str(d)
    else: # undirected
        if G.is_multigraph():
            seen=set()  # helper dict used to avoid duplicate edges
            for s,nbrs in G.adjacency_iter():
                nbr_edges=[ (u,data) 
                            for u,datadict in nbrs.items() 
                            if u not in seen
                            for key,data in datadict.items()]
                deg=len(nbr_edges)
                yield make_str(s)+delimiter+"%i"%(deg)
                for u,d in nbr_edges:
                    if d is None:    
                        yield make_str(u)
                    else:   
                        yield make_str(u)+delimiter+make_str(d)
                seen.add(s)
        else: # undirected single edges
            seen=set()  # helper dict used to avoid duplicate edges
            for s,nbrs in G.adjacency_iter():
                nbr_edges=[ (u,d) for u,d in nbrs.items() if u not in seen]
                deg=len(nbr_edges)
                yield  make_str(s)+delimiter+"%i"%(deg)
                for u,d in nbr_edges:
                    if d is None:    
                        yield make_str(u)
                    else:   
                        yield make_str(u)+delimiter+make_str(d)
                seen.add(s)
Ejemplo n.º 35
0
    def add_edges(self, G, graph_element):
        def edge_key_data(G):
            # helper function to unify multigraph and graph edge iterator
            if G.is_multigraph():
                for u, v, key, data in G.edges(data=True, keys=True):
                    edge_data = data.copy()
                    edge_data.update(key=key)
                    edge_id = edge_data.pop('id', None)
                    if edge_id is None:
                        edge_id = next(self.edge_id)
                        while make_str(edge_id) in self.all_edge_ids:
                            edge_id = next(self.edge_id)
                        self.all_edge_ids.add(make_str(edge_id))
                    yield u, v, edge_id, edge_data
            else:
                for u, v, data in G.edges(data=True):
                    edge_data = data.copy()
                    edge_id = edge_data.pop('id', None)
                    if edge_id is None:
                        edge_id = next(self.edge_id)
                        while make_str(edge_id) in self.all_edge_ids:
                            edge_id = next(self.edge_id)
                        self.all_edge_ids.add(make_str(edge_id))
                    yield u, v, edge_id, edge_data

        edges_element = Element('edges')
        for u, v, key, edge_data in edge_key_data(G):
            kw = {'id': make_str(key)}
            try:
                edge_weight = edge_data.pop('weight')
                kw['weight'] = make_str(edge_weight)
            except KeyError:
                pass
            try:
                edge_type = edge_data.pop('type')
                kw['type'] = make_str(edge_type)
            except KeyError:
                pass
            try:
                start = edge_data.pop('start')
                kw['start'] = make_str(start)
                self.alter_graph_mode_timeformat(start)
            except KeyError:
                pass
            try:
                end = edge_data.pop('end')
                kw['end'] = make_str(end)
                self.alter_graph_mode_timeformat(end)
            except KeyError:
                pass
            source_id = make_str(G.nodes[u].get('id', u))
            target_id = make_str(G.nodes[v].get('id', v))
            edge_element = Element('edge',
                                   source=source_id,
                                   target=target_id,
                                   **kw)
            default = G.graph.get('edge_default', {})
            if self.version == '1.1':
                edge_data = self.add_slices(edge_element, edge_data)
            else:
                edge_data = self.add_spells(edge_element, edge_data)
            edge_data = self.add_viz(edge_element, edge_data)
            edge_data = self.add_attributes('edge', edge_element, edge_data,
                                            default)
            edges_element.append(edge_element)
        graph_element.append(edges_element)
Ejemplo n.º 36
0
 def add_nodes(self, G, graph_element):
     for node, data in G.nodes_iter(data=True):
         node_element = Element("node", id=make_str(node))
         default = G.graph.get('node_default', {})
         self.add_attributes("node", node_element, data, default)
         graph_element.append(node_element)
Ejemplo n.º 37
0
    def add_graph_element(self, G):
        """
        Serialize graph G in GraphML to the stream.
        """
        if G.is_directed():
            default_edge_type = "directed"
        else:
            default_edge_type = "undirected"

        graphid = G.graph.pop("id", None)
        if graphid is None:
            graph_element = self._xml.element("graph",
                                              edgedefault=default_edge_type)
        else:
            graph_element = self._xml.element("graph",
                                              edgedefault=default_edge_type,
                                              id=graphid)

        # gather attributes types for the whole graph
        # to find the most general numeric format needed.
        # Then pass through attributes to create key_id for each.
        graphdata = {
            k: v
            for k, v in G.graph.items()
            if k not in ("node_default", "edge_default")
        }
        node_default = G.graph.get("node_default", {})
        edge_default = G.graph.get("edge_default", {})
        # Graph attributes
        for k, v in graphdata.items():
            self.attribute_types[(make_str(k), "graph")].add(type(v))
        for k, v in graphdata.items():
            element_type = self.xml_type[self.attr_type(k, "graph", v)]
            self.get_key(make_str(k), element_type, "graph", None)
        # Nodes and data
        for node, d in G.nodes(data=True):
            for k, v in d.items():
                self.attribute_types[(make_str(k), "node")].add(type(v))
        for node, d in G.nodes(data=True):
            for k, v in d.items():
                T = self.xml_type[self.attr_type(k, "node", v)]
                self.get_key(make_str(k), T, "node", node_default.get(k))
        # Edges and data
        if G.is_multigraph():
            for u, v, ekey, d in G.edges(keys=True, data=True):
                for k, v in d.items():
                    self.attribute_types[(make_str(k), "edge")].add(type(v))
            for u, v, ekey, d in G.edges(keys=True, data=True):
                for k, v in d.items():
                    T = self.xml_type[self.attr_type(k, "edge", v)]
                    self.get_key(make_str(k), T, "edge", edge_default.get(k))
        else:
            for u, v, d in G.edges(data=True):
                for k, v in d.items():
                    self.attribute_types[(make_str(k), "edge")].add(type(v))
            for u, v, d in G.edges(data=True):
                for k, v in d.items():
                    T = self.xml_type[self.attr_type(k, "edge", v)]
                    self.get_key(make_str(k), T, "edge", edge_default.get(k))

        # Now add attribute keys to the xml file
        for key in self.xml:
            self._xml.write(key, pretty_print=self._prettyprint)

        # The incremental_writer writes each node/edge as it is created
        incremental_writer = IncrementalElement(self._xml, self._prettyprint)
        with graph_element:
            self.add_attributes("graph", incremental_writer, graphdata, {})
            self.add_nodes(G, incremental_writer)  # adds attributes too
            self.add_edges(G, incremental_writer)  # adds attributes too
Ejemplo n.º 38
0
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
Ejemplo n.º 39
0
def generate_ordered_dot(N, name=None):
    """
    The networkx write_dot() function generates
    """
    try:
        import pydot
    except ImportError:
        raise ImportError('to_pydot() requires pydot: '
                          'http://code.google.com/p/pydot/')

    # set Graphviz graph type
    if N.is_directed():
        graph_type = 'digraph'
    else:
        graph_type = 'graph'
    strict = N.number_of_selfloops() == 0 and not N.is_multigraph()

    node_attrs = dict()
    node_attrs["shape"] = "circle"
    node_attrs["width"] = "0.1"
    node_attrs["height"] = "0.1"
    node_attrs["fixedsize"] = "true"
    node_attrs["label"] = ""

    graph_defaults = N.graph.get('graph', {})
    graph_defaults["ratio"] = "auto"
    graph_defaults["labelloc"] = "t"
    graph_defaults["label"] = name
    graph_defaults["pad"] = "1.0"

    if name is None:
        P = pydot.Dot(graph_type=graph_type, strict=strict, **graph_defaults)
    else:
        P = pydot.Dot('"%s"' % name,
                      graph_type=graph_type,
                      strict=strict,
                      **graph_defaults)
    try:
        P.set_node_defaults(**node_attrs)
    except KeyError:
        pass
    try:
        P.set_edge_defaults(**N.graph['edge'])
    except KeyError:
        pass

    for n, nodedata in sorted(N.nodes_iter(data=True),
                              key=lambda n: int(n[0])):
        str_nodedata = dict((k, make_str(v)) for k, v in nodedata.items())
        p = pydot.Node(make_str(n), **str_nodedata)
        P.add_node(p)

    if N.is_multigraph():
        for u, v, key, edgedata in N.edges_iter(data=True, keys=True):
            str_edgedata = dict((k, make_str(v)) for k, v in edgedata.items())
            edge = pydot.Edge(make_str(u),
                              make_str(v),
                              key=make_str(key),
                              **str_edgedata)
            P.add_edge(edge)

    else:

        for u, v, edgedata in sorted(N.edges_iter(data=True),
                                     key=lambda u: int(u[0])):
            str_edgedata = dict((k, make_str(v)) for k, v in edgedata.items())
            if int(v) < int(u):
                edge = pydot.Edge(make_str(v), make_str(u), **str_edgedata)
            else:
                edge = pydot.Edge(make_str(u), make_str(v), **str_edgedata)
            P.add_edge(edge)
    return P
Ejemplo n.º 40
0
def pydot_layout(G, prog='neato', root=None):
    """Create node positions using :mod:`pydot` and Graphviz.

    Parameters
    --------
    G : Graph
        NetworkX graph to be laid out.
    prog : string  (default: 'neato')
        Name of the GraphViz command to use for layout.
        Options depend on GraphViz version but may include:
        'dot', 'twopi', 'fdp', 'sfdp', 'circo'
    root : Node from G or None (default: None)
        The node of G from which to start some layout algorithms.

    Returns
    --------
    dict
        Dictionary of positions keyed by node.

    Examples
    --------
    >>> G = nx.complete_graph(4)
    >>> pos = nx.nx_pydot.pydot_layout(G)
    >>> pos = nx.nx_pydot.pydot_layout(G, prog='dot')

    Notes
    -----
    If you use complex node objects, they may have the same string
    representation and GraphViz could treat them as the same node.
    The layout may assign both nodes a single location. See Issue #1568
    If this occurs in your case, consider relabeling the nodes just
    for the layout computation using something similar to:

        H = nx.convert_node_labels_to_integers(G, label_attribute='node_label')
        H_layout = nx.nx_pydot.pydot_layout(G, prog='dot')
        G_layout = {H.nodes[n]['node_label']: p for n, p in H_layout.items()}

    """
    import pydot
    P = to_pydot(G)
    if root is not None:
        P.set("root", make_str(root))

    # List of low-level bytes comprising a string in the dot language converted
    # from the passed graph with the passed external GraphViz command.
    D_bytes = P.create_dot(prog=prog)

    # Unique string decoded from these bytes with the preferred locale encoding
    D = str(D_bytes, encoding=getpreferredencoding())

    if D == "":  # no data returned
        print("Graphviz layout with %s failed" % (prog))
        print()
        print("To debug what happened try:")
        print("P = nx.nx_pydot.to_pydot(G)")
        print("P.write_dot(\"file.dot\")")
        print("And then run %s on file.dot" % (prog))
        return

    # List of one or more "pydot.Dot" instances deserialized from this string.
    Q_list = pydot.graph_from_dot_data(D)
    assert len(Q_list) == 1

    # The first and only such instance, as guaranteed by the above assertion.
    Q = Q_list[0]

    node_pos = {}
    for n in G.nodes():
        pydot_node = pydot.Node(make_str(n)).get_name()
        node = Q.get_node(pydot_node)

        if isinstance(node, list):
            node = node[0]
        pos = node.get_pos()[1:-1]  # strip leading and trailing double quotes
        if pos is not None:
            xx, yy = pos.split(",")
            node_pos[n] = (float(xx), float(yy))
    return node_pos
Ejemplo n.º 41
0
def to_pydot(N):
    """Returns a pydot graph from a NetworkX graph N.

    Parameters
    ----------
    N : NetworkX graph
      A graph created with NetworkX

    Examples
    --------
    >>> K5 = nx.complete_graph(5)
    >>> P = nx.nx_pydot.to_pydot(K5)

    Notes
    -----

    """
    pydot = _import_pydot()

    # set Graphviz graph type
    if N.is_directed():
        graph_type = 'digraph'
    else:
        graph_type = 'graph'
    strict = nx.number_of_selfloops(N) == 0 and not N.is_multigraph()

    name = N.name
    graph_defaults = N.graph.get('graph', {})
    if name == '':
        P = pydot.Dot('',
                      graph_type=graph_type,
                      strict=strict,
                      **graph_defaults)
    else:
        P = pydot.Dot('"%s"' % name,
                      graph_type=graph_type,
                      strict=strict,
                      **graph_defaults)
    try:
        P.set_node_defaults(**N.graph['node'])
    except KeyError:
        pass
    try:
        P.set_edge_defaults(**N.graph['edge'])
    except KeyError:
        pass

    for n, nodedata in N.nodes(data=True):
        str_nodedata = dict((k, make_str(v)) for k, v in nodedata.items())
        p = pydot.Node(make_str(n), **str_nodedata)
        P.add_node(p)

    if N.is_multigraph():
        for u, v, key, edgedata in N.edges(data=True, keys=True):
            str_edgedata = dict(
                (k, make_str(v)) for k, v in edgedata.items() if k != 'key')
            edge = pydot.Edge(make_str(u),
                              make_str(v),
                              key=make_str(key),
                              **str_edgedata)
            P.add_edge(edge)

    else:
        for u, v, edgedata in N.edges(data=True):
            str_edgedata = dict((k, make_str(v)) for k, v in edgedata.items())
            edge = pydot.Edge(make_str(u), make_str(v), **str_edgedata)
            P.add_edge(edge)
    return P
Ejemplo n.º 42
0
def test_make_str_with_unicode():
    x = "qualité"
    y = make_str(x)
    assert isinstance(y, str)
    assert len(y) == 7
Ejemplo n.º 43
0
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)):
                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(id)
                nodelabels[id] = label
                G.node[id] = {'label': label}
                try:
                    x, y, shape = splitline[2:5]
                    G.node[id].update({
                        'x': float(x),
                        'y': float(y),
                        'shape': shape
                    })
                except:
                    pass
                extra_attr = zip(splitline[5::2], splitline[6::2])
                G.node[id].update(extra_attr)

                try:
                    extra_attr = zip(['color'], [splitline[-3]])
                    G.node[id].update(extra_attr)
                except:
                    pass

        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 = ui
                v = vi
                #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
Ejemplo n.º 44
0
def node_link_graph(data, directed=False, multigraph=True, attrs=None):
    """Return graph from node-link data format.

    Parameters
    ----------
    data : dict
        node-link formatted graph data

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

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

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

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

    Returns
    -------
    G : NetworkX graph
        A NetworkX graph object

    Examples
    --------
    >>> from networkx.readwrite import json_graph
    >>> G = nx.Graph([('A', 'B')])
    >>> data = json_graph.node_link_data(G)
    >>> H = json_graph.node_link_graph(data)

    Notes
    -----
    Attribute 'key' is only used for multigraphs.

    See Also
    --------
    node_link_data, adjacency_data, tree_data
    """
    # Allow 'attrs' to keep default values.
    if attrs is None:
        attrs = _attrs
    else:
        attrs.update(dict((k, v) for k, v in _attrs.items() if k not in attrs))
    multigraph = data.get('multigraph', multigraph)
    directed = data.get('directed', directed)
    if multigraph:
        graph = nx.MultiGraph()
    else:
        graph = nx.Graph()
    if directed:
        graph = graph.to_directed()
    name = attrs['name']
    source = attrs['source']
    target = attrs['target']
    links = attrs['link']
    # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
    key = None if not multigraph else attrs['key']
    graph.graph = data.get('graph', {})
    c = count()
    for d in data['nodes']:
        node = to_tuple(d.get(name, next(c)))
        nodedata = dict((make_str(k), v) for k, v in d.items() if k != name)
        graph.add_node(node, **nodedata)
    for d in data[links]:
        src = tuple(d[source]) if isinstance(d[source], list) else d[source]
        tgt = tuple(d[target]) if isinstance(d[target], list) else d[target]
        if not multigraph:
            edgedata = dict((make_str(k), v) for k, v in d.items()
                            if k != source and k != target)
            graph.add_edge(src, tgt, **edgedata)
        else:
            ky = d.get(key, None)
            edgedata = dict((make_str(k), v) for k, v in d.items()
                            if k != source and k != target and k != key)
            graph.add_edge(src, tgt, ky, **edgedata)
    return graph