Archibald Addelton
Archibald Addelton

Reputation: 23

python networkx connectionstyle arc3 gives me strange result

I want to make a circular network graph with nodes linked by an arc I just started using networkx

I found the correct ways of doing arcs for my edges but some of them have an inverted curve ...

here is the full code

import random
from math import cos, sin
import matplotlib
import networkx as nx
from matplotlib import pyplot as plt
from pyvis.network import Network
import scipy as sp


def get_coordinates_in_circle(n, scale):
    return_list = []
    for i in range(n):
        theta = float(i) / n * 2 * 3.141592654

        y = cos(theta)
        x = sin(theta)
        return_list.append((x * scale, y * scale))
        # print(return_list)
    return return_list


def draw_number(length):
    """determines a random index number for selection."""
    from_index = random.randint(0, length)
    to_index = random.randint(0, length)
    return from_index, to_index


def netw(NodesN):
    G = nx.Graph()

    node_list = []
    fixed_positions = {}  # dict with two of the positions set
    for i in range(1, NodesN + 1):
        node_list.append(i)
    CirclePos = get_coordinates_in_circle(NodesN, 1)
  
    # jump by 1
    from_list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    to_list1 = [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]

    # jump by 2
    from_list2 = [1,3,5,7,9]
    to_list2 =   [3,5,7,9,1]

    # jump by 3
    from_list3 = [1,4,7,10,3 ]
    to_list3 =   [4,7,10,3,6]
    from_list = from_list1
    to_list = to_list1
    
    for i in range(len(node_list)):
        G.add_node(node_list[i])
        fixed_positions[i+1] = CirclePos[i]
    for j in range(len(from_list)):
        G.add_edges_from([(from_list[j], to_list[j])])
    fixed_nodes = fixed_positions.keys()
    pos = nx.spring_layout(G, pos=fixed_positions, fixed=fixed_nodes)
    # pos = nx.kamada_kawai_layout(G, pos=fixed_positions)


    nx.draw_networkx_nodes(G,pos)
    nx.draw_networkx_labels(G,pos)
    nx.draw_networkx_edges(G,pos,arrows=True,connectionstyle=f"arc3,rad=.5")
    # nx.draw_networkx(G,pos)
    plt.show()

netw(10)

it gives me the correct thing except for the 10->1 edge and if I change the "jump by" list the problem change place and make the "inverted" arc when an edge goes from a big number to a small number

I understood part of my problem with this to replace my coordinates in the "get_coordinates_in_circle" func

it just gives me a line instead of a circle (not what I want just an aid to understant my problem)

return_list = [(0,0),(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9),]

my question is: is ther a way to make it thinks its a closed loop?

draw_circular does not do that

Upvotes: 0

Views: 292

Answers (1)

Ben Grossmann
Ben Grossmann

Reputation: 4772

The inconsistency in the arc direction comes from the fact that you're using a Graph instead of a DiGraph. If we change the first line of the netw function definition to G = nx.Graph(), we end up with the following:

enter image description here

Also, if you want to invert the curvature of the edges, you can use a negative number for rad in the connectionstyle specification. For instance, using connectionstyle=f"arc3,rad=-.5" yields the following result:

enter image description here


By the way, here's a refactored version of your code.

import networkx as nx
import numpy as np
import matplotlib.pyplot as plt

def netw(NodesN, jump = 1):
    node_list = list(range(1,NodesN + 1))
    
    from_list = node_list[::jump]
    to_list = from_list[1:] + from_list[:1]

#
# I suspect you're actually trying to do this with the "jump by" number:
#
#     from_list = node_list
#     to_list = from_list[jump:] + from_list[:jump]
    
    G = nx.DiGraph()
    G.add_nodes_from(node_list)
    G.add_edges_from(zip(from_list, to_list))
    
    pos = nx.circular_layout(G)
    
# If you really want the nodes to go clockwise starting from the top, here's a quick approach.
# Just uncomment the block below
#    
#     c,s = pos[node_list[0]]
#     R_mat = np.array([[-s,c],[c,s]])
#     for k,v in pos.items():
#         pos[k] = R_mat @ v    
    
    nx.draw_networkx(G, pos = pos, connectionstyle=f"arc3,rad=.5")
    plt.show()


netw(10, jump = 1)

Upvotes: 1

Related Questions