Matplotlib and Networkx - drawing a self loop node

10,428

It seems that your approach is quite advanced a use of matplotlib, but I would still recommend using a specialized graph plotting library (as does the networkx documentation). As graphs get bigger, more problems arise -- but problems that have already been solved in those libraries.

A "go-to" option is graphviz, which handles drawing multi-graphs reasonably well. You can write dot files from networkx graphs, and then use one of the graph drawing tools (e.g. dot, neato, etc).

Here is an example, building on graph attributes and multigraph edge attributes:

import networkx as nx
from networkx.drawing.nx_agraph import to_agraph 

# define the graph as per your question
G=nx.MultiDiGraph([(1,2),(1,1),(1,2),(2,3),(3,4),(2,4), 
    (1,2),(1,2),(1,2),(2,3),(3,4),(2,4)])

# add graphviz layout options (see https://stackoverflow.com/a/39662097)
G.graph['edge'] = {'arrowsize': '0.6', 'splines': 'curved'}
G.graph['graph'] = {'scale': '3'}
                                                                                
# adding attributes to edges in multigraphs is more complicated but see
# https://stackoverflow.com/a/26694158                    
G[1][1][0]['color']='red'
                                                                                
A = to_agraph(G) 
A.layout('dot')                                                                 
A.draw('multi.png')   

multi-graph with self loops

Note that you can also easily invoke the drawing from within an ipython shell: https://stackoverflow.com/a/14945560

Share:
10,428
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I have this function and I want to draw a self loop. How can I do that?
    The edge exists but I think it's just a point in this exemple is (1,1) and I couldn't add the name of nodes. My goal is from adjacency matrix draw a graph. Is there there is better way to do this?

    import networkx as nx
    import matplotlib.pyplot as plt
    from matplotlib.patches import FancyArrowPatch, Circle
    import numpy as np
    
    def draw_network(G,pos,ax,sg=None):
    
        for n in G:
            c=Circle(pos[n],radius=0.05,alpha=0.7)
            ax.add_patch(c)
            G.node[n]['patch']=c
            x,y=pos[n]
        seen={}
        for (u,v,d) in G.edges(data=True):
            n1=G.node[u]['patch']
            n2=G.node[v]['patch']
            rad=0.1
            if (u,v) in seen:
                rad=seen.get((u,v))
                rad=(rad+np.sign(rad)*0.1)*-1
            alpha=0.5
            color='k'
    
            e = FancyArrowPatch(n1.center,n2.center,patchA=n1,patchB=n2,
                                arrowstyle='-|>',
                                connectionstyle='arc3,rad=%s'%rad,
                                mutation_scale=10.0,
                                lw=2,
                                alpha=alpha,
                                color=color)
            seen[(u,v)]=rad
            ax.add_patch(e)
        return e
    
    
    G=nx.MultiDiGraph([(1,2),(1,1),(1,2),(2,3),(3,4),(2,4),
                    (1,2),(1,2),(1,2),(2,3),(3,4),(2,4)]
                    )
    
    pos=nx.spring_layout(G)
    ax=plt.gca()
    draw_network(G,pos,ax)
    ax.autoscale()
    plt.axis('equal')
    plt.axis('off')
    
    plt.show()
    
  • Daniel
    Daniel about 6 years
    Can you plot this graph with MattPlotLib as well?
  • llinfeng
    llinfeng about 4 years
    For Jupyterlab, Image(A.draw(format='png')) prints the graph inline to the same browser session. Need to import Image through: from IPython.display import Image.