Quindi, il rendering dei grafici è il particolare genio di graphviz, che ha anche diverse librerie che forniscono collegamenti Python. A mio parere, la migliore di queste librerie di bind è pygraphviz. Graphviz è probabilmente la soluzione migliore e probabilmente anche la più semplice.
Il layout particolare si descrive nella sua interrogazione, un gerarchica, schema a strati, viene eseguita senza sforzo da graphviz' dot motore di layout. Il punto esegue il rendering per garantire che il grafico sia disposto in una configurazione ad albero naturale, vale a dire che i nodi padre sono posizionati sopra i propri figli; i nodi di uguale rango (livelli dalla radice) sono equi-posizionati w/r/t l'asse y quando possibile, e la simmetria naturale viene preservata quando possibile.
(Nota: confusamente, dot si riferisce a uno dei diversi motori di layout che compongono graphviz, ma dot è anche il nome e l'estensione di file del formato di file per tutti i documenti graphviz indipendentemente da come sono resi).
Come si può vedere nel mio codice che segue, utilizzando pygraphviz, è semplice selezionare dot come motore di layout per il grafico, anche se non è in realtà il valore di default (neato è).
Ecco un rapido grafico ho fatto e poi resi utilizzando dot --created e reso usando graphviz via pygraphviz.
Si noti che il grafico ha un layout perfetto - i nodi dello stesso grado si trovano sullo stesso livello lungo un asse verticale, i bambini sono resi sotto i genitori e la "simmetria" naturale viene preservata quando possibile (ad esempio, un nodo genitore è posizionato tra e sopra i suoi due nodi figlio. E come puoi vedere, nessuno del mio codice controlla manualmente il layout - graphviz, ovvero punto, lo gestisce automaticamente.
import pygraphviz as PG
A = PG.AGraph(directed=True, strict=True)
A.add_edge("7th Edition", "32V")
A.add_edge("7th Edition", "Xenix")
# etc., etc.
# save the graph in dot format
A.write('ademo.dot')
# pygraphviz renders graphs in neato by default,
# so you need to specify dot as the layout engine
A.layout(prog='dot')
# opening the dot file in a text editor shows the graph's syntax:
digraph unix {
size="7,5";
node [color=goldenrod2, style=filled];
"7th Edition" -> "32V";
"7th Edition" -> "V7M";
"7th Edition" -> "Xenix";
"7th Edition" -> "UniPlus+";
"V7M" -> "Ultrix-11";
"8th Edition" -> "9th Edition";
"1 BSD" -> "2 BSD";
"2 BSD" -> "2.8 BSD";
"2.8 BSD" -> "Ultrix-11";
"2.8 BSD" -> "2.9 BSD";
"32V" -> "3 BSD";
"3 BSD" -> "4 BSD";
"4 BSD" -> "4.1 BSD";
"4.1 BSD" -> "4.2 BSD";
"4.1 BSD" -> "2.8 BSD";
"4.1 BSD" -> "8th Edition";
"4.2 BSD" -> "4.3 BSD";
"4.2 BSD" -> "Ultrix-32";
}
semplicemente perfetto, devo solo per ottimizzare i layout, i colori, il sangue di Gesù ... grazie. =] – BrainStorm
@doug, mi diresti come imposto il livello del nodo (linea) con un parametro? solo per estetica – BrainStorm
@BrainStorm: beh, solitamente si occupa di questo punto senza alcuna configurazione aggiuntiva. Per forzare la configurazione di questo nodo - impostare un vincolo esplicito - non è difficile, ma richiede due passaggi: (i) definire un "sottografo" (gruppo di nodi nel grafico per avere la stessa posizione orizzontale); e (ii) nella definizione del sottografo, impostare l'attributo 'rank', in questo modo: rank = same. Spazio insufficiente nei commenti per spiegare ulteriormente il sottografo, ma questa pagina fornisce un esempio diretto: http://www.graphviz.org/content/cluster – doug