Получение координат разметки вершин графа с помощью python, networkx, pygraphviz

Я хочу создать график с помощью NetworkX, разметить график с помощью Graphviz (через pygraphviz). Я успешно выполнил все примеры из документации примеров NetworkX pygraphviz < / а>

У меня есть вопрос: как мне получить координаты (x, y) и размеры (ширина, высота) вершин обратно в график NetworkX. Это цель. Мне нужны только возможности макета Graphviz, а не возможности рисования. Возможно ли это с использованием этого стека (NetworkX, pygraphviz, graphviz)? Любым другим путем?

Фоновая мотивация такова. Graphviz выводит png, ps, svg и многие другие форматы. Но я не хочу, чтобы меня ограничивали форматы, которые обрабатывает Graphviz. И я хочу иметь возможность постобработать результаты макета, даже если в конечном итоге я буду выводить популярные форматы, такие как Graphviz, которые поддерживает.

Обновление: я переписал вопрос для ясности. Совет по форматам вывода Graphviz упускает суть. Мне нужны данные макета

Обновление 2: было предложено сделать вывод Graphviz в каком-либо формате, из которого я мог бы затем проанализировать данные макета. Предложение было для SVG. Я рассматривал такую ​​возможность. Graphviz выводит json (согласно странице документации по форматам вывода Graphviz) . Мне не удалось заставить его работать на моей установке Windows - по какой-то причине присутствовали не все выходные форматы). Однако меня беспокоит именно такой подход. Разбор форматированного вывода для данных, которые использовались для создания этого вывода, кажется обратным. Думаю, сами данные должны были быть доступны.

Обновление 3. Есть аналогичный вопрос - Как получить координаты макета из graphviz?. Один из ответов предлагает использовать NetworkX. Однако в ответе используется макет, сделанный NetworkX, а не Graphviz. Автор ответа не знал, как получить данные макета Graphviz. Так что мой вопрос остается актуальным, но пока не получил ответа

Обновление 4 - это 07-2019, и я все еще не нашел способа решить эту проблему. Я пометил один ответ как принятый, но с оговоркой - я все еще в неведении, несмотря на полезный совет, содержащийся в этом ответе


person Michael    schedule 18.07.2017    source источник


Ответы (4)


Майкл, я перечитал ваш вопрос и комментарии, и с инструментами, которые я знаю, которые работают (и я знаю, как использовать), это то, что я бы сделал на вашем месте. Я бы нарисовал ваши диаграммы в DOT / GraphViz, а затем выбрал бы удобочитаемый и простой для анализа формат, такой как SVG, "простой" или даже x-dot. Почему? Не для получения самого графика - некоторые из них даже не реализуют графики - а потому, что эти форматы удобочитаемы и содержат координаты X-Y различных компонентов чертежа. Вы можете использовать эти координаты и размеры в своих целях. Некоторые фрагменты простого графика, которые я только что сделал, должны проиллюстрировать. Сначала SVG

<svg width="89pt" height="188pt"

<g id="node1" class="node"><title>A</title>
<ellipse fill="none" stroke="black" cx="54" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="54" y="-158.3" font-family="Times New Roman,serif" font-size="14.00">A</text>

Или в "простом" формате, возможно, самом простом для разбора:

graph 1 0.75 1.5
node A 0.375 1.25 0.75 0.5 A solid ellipse black lightgrey
node B 0.375 0.25 0.75 0.5 B solid ellipse black lightgrey
edge A B 4 0.375 0.99579 0.375 0.88865 0.375 0.7599 0.375 0.64045 solid black
stop

Или VML, похожий на html:

<v:oval style="position:absolute; left: 0.00; top: 0.00; width: 54.00; height: 36.00" filled="false"  >

И т.д.

person TomServo    schedule 18.07.2017
comment
JLH, я хорошо знаю SVG. Graphviz также выводит SVG. Однако я хочу получить данные макета (x, y, ширина, высота узлов), а не какой-либо формат вывода. Я сам позабочусь о выводе. Я не хочу иметь дело с логикой макета. Я подумал, что я четко сформулировал желаемую функциональность в вопросе. Я ошибаюсь. Я поправлю вопрос - person Michael; 19.07.2017
comment
JLH, перечитав ваш ответ, я понял, что не понял его с первого раза. Вы предлагаете, чтобы я заставил Graphviz создать файл SVG, а затем снова проанализировать SVG, чтобы получить данные макета? Если это ваш совет, то моим контраргументом будет - Graphviz поддерживает гораздо более простые для синтаксического анализа форматы, даже json, с данными макета. Так говорится в их документации. По какой-то необъяснимой причине формат json был недоступен в моей установке Graphviz для Windows. Но в любом случае анализ выходного файла кажется обратным, если есть способ получить данные из самой основной библиотеки через pygraphviz. - person Michael; 19.07.2017
comment
@Michael Да, я выбрал SVG, потому что это XML, но есть и другие, о которых я упоминал в отредактированном ответе выше. В моей версии GraphViz нет возможности вывода в JSON, но существует множество форматов вывода, удобочитаемых человеком. Это всего лишь одно разумное решение заявленной вами проблемы. - person TomServo; 19.07.2017
comment
Я написал синтаксический анализатор для простого, но по какой-то причине он не дал мне все элементы, которые мне были нужны - он не дал мне сегменты (группы узлов) IIRC. Я вернусь к нему - это жизнеспособный подход. Тем не менее, я, кажется, добился некоторого прогресса с pygraphviz, буду продолжать это, пока либо не застрянет, либо пока он не заработает. Опубликуем обновление здесь - person Michael; 24.07.2017
comment
Я проголосовал за этот ответ как за принятый. Однако проблема с GraphVis сохраняется на моей машине. Я считаю, что использовать GraphVis рискованно. К сожалению, я не нашел лучшей библиотеки / инструмента - person Michael; 02.07.2019
comment
@ Майкл Спасибо. Как и вы, я какое-то время хотел получить превосходный инструмент, но GraphViz - лучшее, что я нашел, что бесплатно. - person TomServo; 02.07.2019

по поводу обновления 4

это все еще 2019 год, но это отлично подходит для моих нужд

import networkx as nx
G = nx.complete_graph(10)
pos = nx.drawing.nx_agraph.graphviz_layout(G, prog='dot')
print(pos)

дай мне

{0: (327.0, 666.0), 1: (504.0, 594.0), 2: (327.0, 522.0), 3: (449.0, 450.0), 4: (283.0, 378.0), 5: (283.0, 306.0), 6: (473.0, 234.0), 7: (287.0, 162.0), 8: (418.0, 90.0), 9: (287.0, 18.0)}

дикт узлов и позиций!

Приветствует дом

person Dominik Kummer    schedule 11.09.2019

PyGraphviz не имеет API для получения и настройки информации о макете, такой как формы узлов, маршрутизация краев и т. Д. Мне не известен какой-либо интерфейс Python для этих частей библиотеки Graphviz C. Сам Graphviz предоставляет интерфейс Python, включая рендерер, но я не думаю, что он делает именно то, что вы хотите - см. http://www.graphviz.org/pdf/gv.3python.pdf.

Самый простой подход - создать SVG, как предлагает @JHL.

person Aric    schedule 19.07.2017

Вот еще одно решение. Он отличается от Dominik Kummer, поскольку предоставляет объект pygraphviz.AGraph, что позволяет указать произвольные атрибуты gaphviz для настройки макета.

import networkx as nx
import pygraphviz as pgv

g = nx.complete_graph(10)
ag = nx.drawing.nx_agraph.to_agraph(g)
ag.layout(prog='dot')
layout = [ag.get_node(n).attr['pos'] for n in ag.nodes()]
layout = [[int(ss) for ss in s.split(",")] for s in layout]
print(layout)

дай мне:

[[327, 666], [504, 594], [327, 522], [449, 450], [283, 378], [283, 306], [473, 234], [287, 162], [418, 90], [287, 18]]

person Jonathan Laurent    schedule 27.05.2020