U
    9vf6                     @   s   d Z ddlZddlmZ ddlZddlmZ ddddd	d
gZeddddd Z	eddddd Z
dd
 Zdd Zdd	 ZdddZdddZdS )a  
*****
Pydot
*****

Import and export NetworkX graphs in Graphviz dot format using pydot.

Either this module or nx_agraph can be used to interface with graphviz.

Examples
--------
>>> G = nx.complete_graph(5)
>>> PG = nx.nx_pydot.to_pydot(G)
>>> H = nx.nx_pydot.from_pydot(PG)

See Also
--------
 - pydot:         https://github.com/erocarrera/pydot
 - Graphviz:      https://www.graphviz.org
 - DOT Language:  http://www.graphviz.org/doc/info/lang.html
    N)getpreferredencoding)	open_file	write_dotread_dotgraphviz_layoutpydot_layoutto_pydot
from_pydot   w)modec                 C   s.   d}t j|tdd t| }||  dS )zgWrite NetworkX graph G to Graphviz dot format on path.

    Path can be a string or a file handle.
    znx.nx_pydot.write_dot depends on the pydot package, which hasknown issues and is not actively maintained. Consider usingnx.nx_agraph.write_dot instead.

See https://github.com/networkx/networkx/issues/5723   
stacklevelN)warningswarnDeprecationWarningr   writeZ	to_string)GpathmsgP r   =/tmp/pip-unpacked-wheel-_lngutwb/networkx/drawing/nx_pydot.pyr   &   s    rc                 C   s:   ddl }d}tj|tdd |  }||}t|d S )aO  Returns a NetworkX :class:`MultiGraph` or :class:`MultiDiGraph` from the
    dot file with the passed path.

    If this file contains multiple graphs, only the first such graph is
    returned. All graphs _except_ the first are silently ignored.

    Parameters
    ----------
    path : str or file
        Filename or file handle.

    Returns
    -------
    G : MultiGraph or MultiDiGraph
        A :class:`MultiGraph` or :class:`MultiDiGraph`.

    Notes
    -----
    Use `G = nx.Graph(nx.nx_pydot.read_dot(path))` to return a :class:`Graph` instead of a
    :class:`MultiGraph`.
    r   Nznx.nx_pydot.read_dot depends on the pydot package, which hasknown issues and is not actively maintained. Consider usingnx.nx_agraph.read_dot instead.

See https://github.com/networkx/networkx/issues/5723r   r   )pydotr   r   r   readgraph_from_dot_datar	   )r   r   r   dataZP_listr   r   r   r   8   s    
c              	   C   s  d}t j|tdd | dr$d}nd}|  dkrL|rBt }qbt }n|rZt }nt	 }| 
 d}|d	kr~||_|  D ].}|
 d}|d
krq|j|f|  q|  D ]}| }| }	| }
g }g }t|tr||d n |d D ]}||d qt|	tr<||	d n |	d D ]}||d qD|D ]"}|D ]}|j||f|
 qhq`q|  }|r||jd< z|  d |jd< W n ttfk
r   Y nX z|  d |jd< W n ttfk
r    Y nX |S )a  Returns a NetworkX graph from a Pydot graph.

    Parameters
    ----------
    P : Pydot graph
      A graph created with Pydot

    Returns
    -------
    G : NetworkX multigraph
        A MultiGraph or MultiDiGraph.

    Examples
    --------
    >>> K5 = nx.complete_graph(5)
    >>> A = nx.nx_pydot.to_pydot(K5)
    >>> G = nx.nx_pydot.from_pydot(A)  # return MultiGraph

    # make a Graph instead of MultiGraph
    >>> G = nx.Graph(nx.nx_pydot.from_pydot(A))

    znx.nx_pydot.from_pydot depends on the pydot package, which hasknown issues and is not actively maintained.

See https://github.com/networkx/networkx/issues/5723r   r   NFTgraph" )noder   edgenodesr   r"   r#   )r   r   r   Z
get_strictget_typenxZ
MultiGraphZGraphZMultiDiGraphZDiGraphget_namestripnameZget_node_listadd_nodeZget_attributesZget_edge_list
get_sourceZget_destination
isinstancestrappendadd_edger   Zget_node_defaults
IndexError	TypeErrorZget_edge_defaults)r   r   Z
multiedgesNr)   pneuvattrsdZunodesZvnodesZsource_nodeZdestination_nodeZpattrr   r   r   r	   b   sd    





c                 C   s    d| ko| d dkp| d dkS )N:r   r    r   )r9   r   r   r   _check_colon_quotes   s    r=   c                 C   s  ddl }d}tj|tdd |  r*d}nd}t| dkoD|   }| j}| j	
di }|dkrz|jd||d	|}n |jd
| d
f||d	|}z|jf | j	d  W n tk
r   Y nX z|jf | j	d  W n tk
r   Y nX | jddD ]j\}}	dd |	 D }
t|}t|p>tdd |
 D }|rNtd|j|f|
}||  q|  r| jdddD ]\}}}}dd | D }t|t| }}t|pt|ptdd | D }|rtd|j||fdt|i|}|| qn| jddD ]\}}}dd | D }t|t| }}t|pxt|pxtdd | D }|rtd|j||f|}|| q"|S )a  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
    -----

    r   Nznx.nx_pydot.to_pydot depends on the pydot package, which hasknown issues and is not actively maintained.

See https://github.com/networkx/networkx/issues/5723r   r   Zdigraphr   r!   )
graph_typestrictr    r"   r#   T)r   c                 S   s   i | ]\}}t |t |qS r   r-   .0kr7   r   r   r   
<dictcomp>   s      zto_pydot.<locals>.<dictcomp>c                 s   s"   | ]\}}t |pt |V  qd S Nr=   rA   r   r   r   	<genexpr>  s   zto_pydot.<locals>.<genexpr>zNode names and attributes should not contain ":" unless they are quoted with "".                For example the string 'attribute:data1' should be written as '"attribute:data1"'.                Please refer https://github.com/pydot/pydot/issues/258)r   keysc                 S   s&   i | ]\}}|d krt |t |qS )keyr@   rA   r   r   r   rD     s       c                 s   s"   | ]\}}t |pt |V  qd S rE   rF   rB   rC   valr   r   r   rG     s   a   Node names and attributes should not contain ":" unless they are quoted with "".                    For example the string 'attribute:data1' should be written as '"attribute:data1"'.                    Please refer https://github.com/pydot/pydot/issues/258rI   c                 S   s   i | ]\}}t |t |qS r   r@   rA   r   r   r   rD   (  s      c                 s   s"   | ]\}}t |pt |V  qd S rE   rF   rJ   r   r   r   rG   .  s   )r!   )r   r   r   r   Zis_directedr&   Znumber_of_selfloopsZis_multigraphr)   r   getZDotZset_node_defaultsKeyErrorZset_edge_defaultsr$   itemsr-   r=   any
ValueErrorNoder*   edgesZEdger/   )r2   r   r   r>   r?   r)   Zgraph_defaultsr   r4   ZnodedataZstr_nodedataZraise_errorr3   r6   r7   rI   ZedgedataZstr_edgedatar#   r   r   r   r      s    
 





neatoc                 C   s"   d}t j|tdd t| ||dS )a=  Create node positions using Pydot and Graphviz.

    Returns a dictionary of positions keyed by node.

    Parameters
    ----------
    G : NetworkX Graph
        The graph for which the layout is computed.
    prog : string (default: 'neato')
        The name of the GraphViz program 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
    -------
      Dictionary of (x, y) positions keyed by node.

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

    Notes
    -----
    This is a wrapper for pydot_layout.
    znx.nx_pydot.graphviz_layout depends on the pydot package, which hasknown issues and is not actively maintained. Consider usingnx.nx_agraph.graphviz_layout instead.

See https://github.com/networkx/networkx/issues/5723r   r   )r   progroot)r   r   r   r   )r   rT   rU   r   r   r   r   r   ?  s    c                 C   sV  ddl }d}tj|tdd t| }|dk	r<|dt| |j|d}t|t d}|d	krt	d
| d t	  t	d t	d t	d t	d| d dS |
|}t|dkst|d }	i }
|  D ]}t|}t|rtd|| }|	|}t|tr|d }| dd }|dk	r|d\}}t|t|f|
|< q|
S )a  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()}

    r   Nznx.nx_pydot.pydot_layout depends on the pydot package, which hasknown issues and is not actively maintained.

See https://github.com/networkx/networkx/issues/5723r   r   rU   )rT   )encodingr!   zGraphviz layout with z failedzTo debug what happened try:zP = nx.nx_pydot.to_pydot(G)zP.write_dot("file.dot")zAnd then run z on file.dotr
   zNode names and node attributes should not contain ":" unless they are quoted with "".                For example the string 'attribute:data1' should be written as '"attribute:data1"'.                Please refer https://github.com/pydot/pydot/issues/258r<   ,)r   r   r   r   r   setr-   Z
create_dotr   printr   lenAssertionErrorr$   r=   rP   rQ   r'   Zget_noder,   listZget_possplitfloat)r   rT   rU   r   r   r   ZD_bytesDZQ_listQZnode_posr4   Zstr_nZ
pydot_noder"   posZxxyyr   r   r   r   h  sH    &

)rS   N)rS   N)__doc__r   localer   Znetworkxr&   Znetworkx.utilsr   __all__r   r   r	   r=   r   r   r   r   r   r   r   <module>   s(   




)au
)