Преобразование единиц Matplotlib и Networkx / Pygraphviz в общую единицу - PullRequest
0 голосов
/ 23 октября 2019

Я пытаюсь автоматически масштабировать график networkx на основе количества узлов и наличия узлов, которые перекрываются в горизонтальном или вертикальном направлении (т. Е. Если бы все узлы находились на одной линии, они пересеклись бы). Чтобы сделать это, я смотрю на положение каждого узла и проверяю, находится ли позиция плюс размер узла между любыми другими координатами узла плюс размер узла. Чтобы получить позиции узлов, я использую networkx.nx_agraph.graphviz_layout. Проблема в том, что позиции и размер узла не совпадают.

Networkx вызывает pyplot.scatter под капотом (источник: https://networkx.github.io/documentation/networkx-1.10/_modules/networkx/drawing/nx_pylab.html#draw_networkx_nodes), который принимает размер узла в виде площади в пикселях (источник: https://stackoverflow.com/questions/14827650/pyplot-scatter-plot-marker-size).

Networkx рисует график с узлами круга, поэтому исходя из этого было бы разумно, чтобы для преобразования размера узла в дюймы я сделал бы node_size * 4 / (math.pi * DPI), где DPI - это DPI, используемый Matplotlib. В моем коде это не похоже на работу. Я также попытался взять квадратный корень размера узла и разделить его на DPI, но это тоже не сработало.

В настоящее время проблема заключается в том, что я не могу определить, какие узлы перекрываются.

В итоге: если я строю график сети x с узлами окружности, как я могу преобразовать размер узла и / или позиции Pygraphviz в общую единицу?

Возможно, мойкод неправильный, поэтому вот короткий воспроизводимый пример:

NODE_SIZE = 300
DPI = 100
mpl.rcParams['figure.dpi'] = DPI

G = nx.gnp_random_graph(50, 0)
pos = nx.nx_agraph.graphviz_layout(G)
tmp_pos = sorted(pos.items(), key=lambda x: x[1][0]) # Sort it by x value so you only have to check to the right of the node in the list of positions
node_size_inches = NODE_SIZE * 4 / (math.pi * DPI) # This is my attempt at getting the height/width of the nodes

i = 0
for key, xy in tmp_pos:
    x = xy[0]
    overlapping = []

    # Since list is sorted by x, you only need to check nodes to the right
    for k, xyt in tmp_pos[i+1:]:

        xt = xyt[0]

        # Check for overlapping nodes to the right
        if x <= xt <= x + node_size_inches:
            overlapping.append(k)

        # Since list is sorted by x, if the previous condition fails, nothing after can be applicable
        else:
            break

    if overlapping: print("{}:{}".format(key, overlapping))

    i += 1

nx.draw(G, pos=pos, with_labels=True)
...