Search code examples
pythonmatplotlibnetworkxdirected-graphdigraphs

how to set a top-down position in a graph networkx


This is my extended work from here. I would like to set the last element 'm' in the unique_liss appears at the top position of the rest nodes like thisenter image description here. However, most of the image generated would be like this:enter image description here

this is my codes:

Unique_liss= ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm']

edgesList= [('a', 'b'), ('b', 'c '), ('c ', 'd'), ('d', 'e'), ('d', 'f'), ('e', 'g'), ('f', 'g'), ('g', 'h'), ('h', 'i '), ('i ', 'j'), ('j', 'k'), ('j', 'l'), ('k', 'm'), ('l', 'm')]

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
for node in edgesList:
    print('node-', node)
    G.add_edge(*node,sep=',')

A = nx.adjacency_matrix(G).A
import numpy as np
seed = 31
pos = nx.spring_layout(G)
plt.figure(figsize=(15,8))
nx.draw(G, pos=pos, with_labels=True, node_size = 1500,
        seed=seed, node_color = 'skyblue')

Although i change the for ..loop into a reversed loop as below:

for node in reversed(edgesList):
    print('node-', node)
    G.add_edge(*node,sep=',')

it's doesn't guarantees that the last element of the node 'm' to be appread on the top position of the rest. Appreciate if anyone can help on how to set the last node to be permanently appear at the top position ?


Solution

  • Here is an idea that updates the positions in the layout based on the relative position of a node of interest to the center of the graph:

    def get_graph_centroid(pos):
        return np.mean(np.array([a for a in pos.values()]), axis=0)
    
    def find_flip(node_of_interest, pos):
    
        node_x, node_y = pos[node_of_interest]
        cx, cy = get_graph_centroid(pos)
    
        flip = [1,1]
    
        if node_x < cx:
            flip[0] = -1
        if node_y < cy:
            flip[1] = -1
    
        return flip
    
    def make_flip(pos, flip):
    
        x,y = flip
        pos = {key: (x*a,y*b) for key, (a,b) in pos.items()}
    
        return pos
    
    
    
    pos = nx.spring_layout(G)
    plt.subplot(121)
    nx.draw(G, pos=pos, with_labels=True, node_size = 500,
            seed=seed, node_color = 'skyblue')
    plt.title('normal layout')
    
    plt.subplot(122)
    flip = find_flip('m', pos)
    pos = make_flip(pos, flip)
    nx.draw(G, pos=pos, with_labels=True, node_size = 500,
            seed=seed, node_color = 'skyblue')
    plt.title('flipped layout')
    

    enter image description here

    Note that this code only ensures that the node is top right wrt the center, not that is the closest node to the top right corner