Я пытаюсь автоматически масштабировать график 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)