pythongraphnetworkxdigraphsgraph-drawing

Python - How to display directed multigraph with different node shapes using networkx.draw()


I have seen a similar question here and its accepted answer for a digraph. The idea for a digraph is to add nodes to as many different subgraphs as there are node shapes ('o', 'd', 's', etc.), then add edges between nodes and finally plot each using the Python networkx library.

For a multidigraph, I tried the sample code below without adding edges, just to check that node shapes are as required. After poring over the official doc, I only can draw a blank graph (literally). So are the files to which I write.

I'm missing something basic. Any pointer welcome.

import matplotlib.pyplot as plt
import networkx as nx
import pydot

rn = list()
rn_colmap = []                     # round node color_map
rn_sizmap = []                     # round node

sn = list()
sn_colmap = []                     # square node color_map
sn_sizmap = []                     # square node size_map

g_out = "/whatever/path/to/file_out"

G = nx.MultiDiGraph()

for n_idx in range(len(my_nodes)):
    if my_nodes[n_idx] in nodes_A:
        rn.append(my_nodes[n_idx])
        rn_colmap.append('r')
        rn_sizmap.append(300)
    else:
        sn.append(my_nodes[n_idx])
        sn_colmap.append('b')
        sn_sizmap.append(600)

rnG = G.subgraph(rn)
snG = G.subgraph(sn)

rn_pos = nx.spring_layout(rnG,iterations=3)
sn_pos = nx.spring_layout(snG,iterations=3)

plt.figure(figsize=(12,12), frameon=False)
    
nx.draw(rnG,
        rn_pos,
        node_size = rn_sizmap,
        node_color = rn_colmap,
        node_shape = 'o',
        alpha=0.9,
        with_labels = True,
        font_size=12,
        font_weight='bold',
        font_family='sans-serif',
       )

nx.draw(snG,
        sn_pos,
        node_size = sn_sizmap,
        node_color = sn_colmap,
        node_shape = 's',
        alpha=0.9,
        with_labels = True,
        font_size=12,
        font_weight='bold',
        font_family='sans-serif',
       )

nx.drawing.nx_pydot.write_dot(G, g_out + '.dot')
plt.savefig(g_out + '.png')
nx.write_gml(G,g_out + '.gml.gz')    

plt.show()

G.clear()
plt.close()

Solution

  • I just realized that I need to properly declare my sub-graphs before populating them with the appropriate complete graph's nodes of interest.

    So the code becomes:

    import matplotlib.pyplot as plt
    import networkx as nx
    import pydot
    
    rn = list()
    rn_colmap = []                     # round node color_map
    rn_sizmap = []                     # round node
    
    sn = list()
    sn_colmap = []                     # square node color_map
    sn_sizmap = []                     # square node size_map
    
    g_out = "/whatever/path/to/file_out"
    
    G = nx.MultiDiGraph()
    rnG = G.__class__()                # declare/instantiate sub-graphs
    snG = G.__class__()
    
    for n_idx in range(len(my_nodes)):
        G.add_node(my_nodes[n_idx])    # populate main graph
        
        if my_nodes[n_idx] in nodes_A:
            rn.append(my_nodes[n_idx])
            rn_colmap.append('r')
            rn_sizmap.append(300)
        else:
            sn.append(my_nodes[n_idx])
            sn_colmap.append('b')
            sn_sizmap.append(600)
    
    rnG = G.subgraph(rn)
    snG = G.subgraph(sn)
    
    # Remaining code is identical to corresponding code section in OP:
    
    rn_pos = nx.spring_layout(rnG,iterations=3)
    sn_pos = nx.spring_layout(snG,iterations=3)
    
    plt.figure(figsize=(12,12), frameon=False)
    
    nx.draw(rnG,
            rn_pos,
            node_size = rn_sizmap,
            node_color = rn_colmap,
            node_shape = 'o',
            alpha=0.9,
            with_labels = True,
            font_size=12,
            font_weight='bold',
            font_family='sans-serif',
           )
    
    nx.draw(snG,
            sn_pos,
            node_size = sn_sizmap,
            node_color = sn_colmap,
            node_shape = 's',
            alpha=0.9,
            with_labels = True,
            font_size=12,
            font_weight='bold',
            font_family='sans-serif',
           )
    
    nx.drawing.nx_pydot.write_dot(G, g_out + '.dot')
    plt.savefig(g_out + '.png')
    nx.write_gml(G,g_out + '.gml.gz')    
    
    plt.show()
    
    G.clear()
    plt.close()