Björn Klippstein

Graphviz-Tutorial

Klippstein IT Service

Aus 4webmaster.de

Wechseln zu: Navigation, Suche
Es gibt auch eine Version mit einzelnen Seiten, Quicklinks für diese Version:


Inhaltsverzeichnis

Mit Graphviz lassen sich schnell und einfach Diagramme erstellen. Strukturdiagramme, Pfeildiagramme und andere Diagramme; automatisch erzeugte Diagramme und aufwändig manuell gestaltete Diagramme.

Auf dieser Seite bekommen Sie konkrete Hilfestellung bei der Erstellung von Diagrammen mit Graphviz. Von einer ersten Einführung bis hin zu den Besonderheiten und Fallstricken der Software, die es (wie immer) auch hier gibt.

Graphviz ist ein Softwarepaket, das sich von den normalen WYSIWYG-Zeichenprogrammen unterscheidet. Anders als bei einem WYSIWYG-Zeichenprogramm zeichnet der Benutzer ein Diagramm nicht wirklich selbst. Stattdessen beschreibt er das Diagramm nur in einer Beschreibungssprache namens DOT. Das genaue Layout wird dann automatisch bestimmt.

Hier gibt es eine Analogie zu HTML, der Beschreibungssprache von Webseiten. Genauso wie HTML nur den Inhalt und die Struktur einer Webseite bescheibt (und dem Browser die Details der Darstellung überlässt), beschreibt DOT nur die Struktur und das Aussehen einer Grafik.

Was bei HTML die Aufgabe des Browsers ist (also die konkrete Darstellung), ist bei Graphviz die Aufgabe des Renderers. Der Renderer macht aus einem DOT-Quellcode ein Diagramm und gibt es als Grafik aus.

Erste Schritte

Zunächst ein einfaches Beispiel, an dem Sie das Grundprinzip erkennen können. Der folgendene DOT-Quelltext ist wohl selbsterklärend und erzeugt untenstehendes Diagramm:

digraph G {
 DOT -> Strukturdiagramme
 DOT -> Pfeildiagramme
 DOT -> MindMaps
}
Hallo Welt

Begriffsklärung

  • Das Programmpaket, mit dem wir hier Diagramme erstellen, heißt Graphviz. Graphviz ist freie Software und für die meisten Betriebssysteme verfügbar.
  • Graphviz enthält insbesondere die Renderer, die letztlich Diagramme erzeugen. Es gibt verschiedene Renderer. Sie heißen dot, neato, fdp, circo und twopi. Je nach verwendetem Renderer sehen die erzeugten Diagramme anders aus.
  • Die Renderer geben Diagramme in den Formaten GIF, PNG, SVG oder PostScript (welches sich nach PDF wandeln lässt) aus.
  • Die Beschreibungssprache für die Diagramme heißt DOT. Alle Renderer interpretieren DOT-Quellcode.
  • Der Renderer dot heißt leider genauso wie die Sprache DOT, mit der die Diagramme beschrieben werden.

Wofür wird Graphviz verwendet?

Graphviz wird gerne zur Erstellung automatischer Diagramme verwendet. Auch zur Integration in Wikis eignet es sich hervorragend.

Wikis: Dadurch, dass die Diagramme nur beschrieben werden statt detailliert gestaltet, lässt sich Graphiz gut in Wikis integrieren. In einem Wiki wird mit Texten ja genauso umgegangen: Mit einer Markup-Language beschreibt man die Struktur des darzustellenden Textes, um die Details der Darstellung kümmert sich die Wiki-Software. Für einige große Wiki-Suiten (Mediawiki, TWiki, DokuWiki) existieren entsprechende Plugins (siehe Web-Links)

Automatische Strukturdiagramme: Beziehungsnetzwerke (wie z.B. soziale Netzwerke), Daten mit komplexen Hierarchien (wie etwa XML-Dokumente) oder gar multihierarchisch strukturierte Daten (wie z.B. das Kategoriensystem der Wikipedia) sind für Menschen nur mit großer Mühe als Gesamtheit erfassbar. Eine grafische Darstellung dieser Strukturen erleichtert es dem menschlichen Gehirn sehr, komplexe Dinge zu erfassen, übergreifende Muster zu erkennen und den Überblick zu bewahren. Um das zu erreichen, kann man die bestehenden Daten in DOT umwandeln und an Graphviz übergeben.

Weniger geeignet ist das Graphiz-Programmpaket, wenn ein Diagramm optisch sehr aufwendig gestaltet und die Darstellung bis ins letzte Detail festgelegt werden soll. Die Stärke von Graphviz ist, schon aus spärlichen Struktur-Angaben direkt ein lesbares Diagramm zu erzeugen.

Eine umfangreiche Liste von Anwendungen, die Graphviz nutzen, findet sich hier [1] auf den Seiten von graphviz.org.

Wie binde ich DOT-Diagramme in mein Wiki ein?

Zunächst muss das entsprechende Plugin / die entsprechende Extension installiert werden, damit das Wiki überhaupt mit DOT umgehen kann.

Dann kann man DOT direkt mit in den Quelltext der Seite schreiben. Um dem Wiki mitzuteilen, dass die folgenden Zeilen als DOT-Quellcode zu interpretieren sind und an den entsprechenden Renderer weitergegeben werden sollen, wird der DOT-Quellcode mit speziellen Tags eingeschlossen. In Mediawiki heißt der Tag graphviz, in TWiki heißt er dot.

In diesem Tutorial wird die Graphviz-Extension für MediaWiki [2] verwendet. Obiges Diagramm lässt sich wie folgt in ein MediaWiki einbinden (wenn die Extension installiert ist):

<graphviz>
     digraph G {
       DOT -> Strukturdiagramme
       DOT -> Pfeildiagramme
       DOT -> MindMaps
     }
 </graphviz>

Ein Beispieldiagramm

Am folgenden Diagramm können Sie die Basics von DOT erlernen. Es ist ist dem User-Guide von graphviz.org entnommen [3]. Im DOT-Quellcode werden drei verschiedene Arten von Objekten verwendet:

  • graph: Im Beispiel gibt es genau einen Graph. Er ist gerichtet (deswegen heißt es digraph) und heißt G. Es gibt auch Diagramme mit ungerichteten Graphen, dazu später mehr. Außerdem kann ein Diagramm mehrere Graphen enthalten.
  • node: Die Nodes (zu deutsch "Knoten") sind die Elemente, die durch den Graphen miteinander verknüpft werden. Im Beispiel heißen die Nodes main, parse, execute, usw. Ein Node muss nicht extra definiert werden, er entsteht bei seiner ersten Verwendung.
  • edge: Die Edges (zu deutsch "Kanten") sind die Verknüpfungen zwischen den Nodes. Eine gerichtete Verknüpfung entsteht, wenn man zwei Nodes mit -> verbindet.


digraph G {
 main -> parse -> execute
 main -> init
 main -> cleanup
 execute -> make_string
 execute -> printf;
 init -> make_string;
 main -> printf;
 execute -> compare;
}
Graphviz-Beispiel


Die Verknüpfungen können untereinander oder auch direkt hintereinander geschrieben werden. Man kann sie mit einem Semikolon trennen oder es lassen, je nachdem wie man es von anderen Sprachen gewöhnt ist.



Grafische Eigenschaften

Farben und Fonts anpassen

Diagramme sollen nicht nur übersichtlich sein, sie sollen meist auch angenehm anzuschauen sein. Ihr Erscheinungsbild lässt sich so anpassen, dass es sich in die Site integriert. Dazu dienen die ersten drei Zeilen in untenstehendem Diagramm-Quellcode (der Rest ist unverändert).


digraph G {
 node [fontname=Verdana,fontsize=12]
 node [style=filled]
 node [fillcolor="#EEEEEE"]
 node [color="#EEEEEE"]
 edge [color="#31CEF0"]
 
 main -> parse -> execute
 main -> init
 main -> cleanup
 execute -> make_string
 execute -> printf
 init -> make_string
 main -> printf
 execute -> compare
}
Graphviz-Beispiel Farben und Fonts anpassen
Angepasste Farben und Fonts


Mit node und edge wird die Default-Darstellung von Nodes und Edges festgelegt. Im obigen Beispiel werden fünf Attribute von node neu gesetzt sowie ein Attribut von edge. Ein Attribut setzt man durch ein Schlüssel-Wert-Paar, z.B. fontname=Verdana. Diese Attribut-Zuweisung wird in eckige Klammern eingeschlossen und hinter das Element notiert, für das es gelten soll. Mehrere Attribut-Zuweisungen in einer Zeile sind auch möglich, sie werden mit Komma getrennt.

Die Attribute von node gelten für alle Nodes des Diagrammes. Und zwar ab dem Moment, wo sie festgelegt werden: Wenn z.B. die Farbe von Nodes ganz oben im DOT-Quelltext festgelegt wird werden alle anschließend erstellten Nodes in dieser Farbe dargestellt. Wenn die Farbe erst in der Mitte des Quelltextes festgelegt wird, ist nur der untere Teil des Graphen mit der Farbe dargestellt.

Genauso verhält es sich mit den Attributen von edge. Auch für den Graphen selbst (graph) können Attribute gesetzt werden. Eine vollständige Liste aller Attribute findet sich in [4]

Die Richtung des Diagrammes festlegen

Ein Attribut von graph ist seine Orientierung: Soll er von oben nach unten (Default-Einstellung) oder von links nach rechts dargestellt werden? Dazu dient das Attribut rankdir, es legt die Orientierung des Graphen fest. Erlaubt sind die Werte TB (Default), LR (untenstehendes Beispiel), BT (von unten nach oben) oder RL (von rechts nach links).


digraph G {
 graph [rankdir=LR] 
 
 main -> parse -> execute
 main -> init
 main -> cleanup
 execute -> make_string
 execute -> printf
 init -> make_string
 main -> printf
 execute -> compare
}
rankdir-Attribut (Graphviz)
rankdir=LR


Die Zeilen zur Anpassung der Farben und Fonts werden in den Quelltextbeispielen jetzt weggelassen, obwohl sie in den zugehörigen Diagrammen natürlich nach wie vor vorhanden sind.

Das Aussehen einzelner Elemente ändern

Attribute können auch gezielt für einzelne Elemente gesetzt werden. Dazu werden sie direkt hinter dem Element notiert.

Das folgende Beispiel ist direkt im Quellcode kommentiert.


digraph G {
/* Node main initialisieren und */
/* Attribute für ihn setzen     */ 
 main [shape=box, color=deeppink]
 
 main -> parse -> execute
 
/* Node init initialisieren,       */
/* Edge von main nach init und     */
/* Attribute für diese Edge setzen.*/
 main -> init [color=deeppink, 
               arrowhead=vee, 
               arrowtail=vee]
 
/* Attribute für den Node init    */
/* setzen. Das geht auch, nachdem */
/* er schon initialisiert ist.    */
 init [shape=box, color=deeppink]
 
 main -> cleanup
 execute -> make_string
 execute -> printf
 init -> make_string
 main -> printf
 
/* Bei Edges kann man die        */
/* Attribute nicht im nachhinein */
/* setzen. Dabei wird nämlich    */
/* eine zweite Edge erzeugt.     */
 execute -> compare
 execute -> compare [color=green, 
                     arrowtail=tee]
}
Beispieldiagramm Graphviz-Attribute
Elemente einzeln formatieren


Die Darstellung von Nodes verändern

Die folgende Grafik, die einer MindMap ähnelt, zeigt eine Übersicht über Attribute, die das Aussehen eines einzelnen Nodes ändern. Die blauen Linien haben hier die Bedeutung "ist Attribut von".

  • Farbe: Die Farben werden mit color und fillcolor bestimmt. Erlaubt sind z.B. Farbnamen ("red"), hexadezimale Farbangaben ("#EEEEEE") oder Farbnummern (7). Die Farbnummern beziehen sich auf eine vorher mit colorsheme gesetzte Farbpalette . Wenn z.B. colorsheme=spectral7, dann bezeichnet fillcolor=7 die Farbe mit der Nummer 7 in dieser Palette (ein gedämpftes blau). Die Farbnamen und eine umfangreiche Bibliothek von Farbpaletten für verschiedene Zwecke finden sich unter [5]. Die Angabe von fillcolor funktioniert leider nur mit der zusätzlichen Angabe von style=filled.
  • Größe: Die Größe eines Node wird normalerweise automatisch bestimmt, je nach dem wieviel Text er enthält. Mit height und width lassen sich aber auch Mindesthöhe und Mindestbreite angeben. Wählt man aber fixedsize=true für den Node, ändern die Parameter ihre Bedeutung, jetzt legt man damit die Höhe und Breite direkt fest.
  • Form: Außer der standardmäßigen Ellipse können Nodes vielfältige Formen annehmen. Bei shape=plaintext wird gar keine Form um den Node herum gezeichnet. Außerdem gibt es noch shape=record, damit erzeugt man die verschachtelten Nodes, die auch in untenstehendem Diagramm verwendet werden. Dazu später mehr. Wählt man shape=polygon (Vieleck), dann kann man die Form des entstehenden Polygons mit weiteren Node-Attributen (sides, regular, distortion und skew) spezifizieren. Das Attribut orientation dreht die Form des Node um den angegebenen Winkel (0°..360°). Alle Möglichkeiten von shape finden sich unter [6].
  • Rahmenlinie: Mit dem style - Attribut läßt sich das Aussehen eines Nodes weiter spezifizieren. Z.B. die Art der Rahmenlinie: durchgezogen, mit abgerundeten Ecken, gepunktet, gestrichelt oder fett. (Mit dem Node-Attribut peripheries=2 kann man übrigens den Node auch mit einer doppelten Rahmenline umgeben.)
    style=invis macht ein Node komplett unsichtbar. Damit kann man z.B. die Plazierung der anderen Nodes beeinflussen.
Übersicht: Node-Attribute von Graphviz


Die Darstellung von Edges verändern

Auch die Darstellung von Edges lässt sich vielfältig verändern. Am Ende des Abschnittes finden Sie wieder eine zusammenfassende MindMap.

  • Linie: Die Art der Linie, mit der eine Edge gezeichnet wird, lässt sich mit dem style - Attribut bestimmen. Wie Rahmenlinien von Nodes können Edges durchgezogen, fett, gestrichelt, gepunktet oder unsichtbar sein.
  • Farbe: Für die Farbe der Edge verwendet man das color - Attribut ebenso wie bei Nodes.
  • Pfeilspitzen: Statt der standardmäßigen Pfeilspitzen können die Enden der Edges mit vielfältigen Symbolen gezeichnet werden. Den Punkt 'dot' haben Sie ja schon kennengelernt. Alle Möglichkeiten finden Sie hier [7]. Das Attribut arrowhead legt das Ziel der Edge fest, arrowtail die Quelle. Mit arrowsize können Sie die Pfeilspitzen vergrößern oder verkleinern. arrowsize=0.5 sorgt beispielsweise für halb so große Pfeilspitzen. Beide Enden können leider nur gemeinsam skaliert werden.
  • Verbindung zum Node: Mit headclip=false und tailclip=false können Sie bewirken, dass eine Edge nicht nur bis zum Außenrand eines Nodes gezeichnet wird. Stattdessen wird die Linie des Edge bis in die Mitte des Node geführt. Im obigen Diagramm der Node-Attribute wurde das z.B. eingesetzt, um die Abhängigkeit von fillcolor und style=filled zu visualisieren. Die Attribute dieser Edge lauten:
    [color=gold1, arrowhead=none, arrowtail=none, headclip=false, tailclip=false]
    Nützlich ist das auch für unsichtbare Nodes (style=invis). Es gibt allerdings elegantere Möglichkeiten, das Aussehen des Diagrammes zu beeinflussen, als der Einsatz unsichtbarer Nodes.
  • Verbindungspunkte zusammenfassen: Normalerweise wird für jede neue Edge ein neuer Verbindungspunkt am Rand des Edge gezeichnet. Wenn Sie mehrere Verbindungspunkte zusammenfassen wollen, weisen Sie ihnen das gleiche sametail - Attribut zu, z.B. Beispiel sametail=gruppe1. Analog funktioniert das auch mit dem Zielpunkt der Edges (samehead).
Übersicht: Edge-Attribute von Graphviz



Beschriftungen

Beschriftung von Nodes

Es gibt drei Möglichkeiten, einen Node zu beschriften:

  • Standardmäßig verwendet Graphviz den Namen eines Nodes als Beschriftung. Das funktioniert prima für einzelne Wörter ohne Sonderzeichen.
  • Wenn Sie Spaces, Sonderzeichen oder Zeilenumbrüche verwenden wollen, können Sie den Namen des Nodes in Anführungszeichen setzen. Auf diese Weise geben Sie dem Node einen möglicherweise komplex formatierten Namen. Graphviz verwendet auch hier den Namen des Nodes als Beschriftung. Der Nachteil dieses Vorgehens ist, dass Sie den Node im Folgenden immer unter seinem möglicherweise komplex formatierten Namen ansprechen müssen. Verwenden Sie Node-Namen in Anführungszeichen also nur dann, wenn der Name trotzdem handlich bleibt, oder wenn Sie den Node nur selten mit anderen Nodes vernetzen.
  • Am flexibelsten ist die Beschriftung eines Nodes mit dem label-Attribut. Geben Sie dem Node einen handlichen Namen, und legen Sie mit dem label-Attribut eine Beschriftung fest, die vom Namen des Nodes abweicht. Sie können auch Zeilenumbrüche einbauen:
    • \n erzeugt einen normalen Zeilenumbruch.
    • Die Varianten \l und \r erzeugen einen Zeilenumbruch und richten die umgebrochene Zeile linksbündig bzw. rechtsbündig aus.
      Der Einsatz von \l und \r sollte wohlüberlegt sein, insbesondere wenn man nicht mit dot rendert, sondern mit neato, fdp, circo oder twopi. Für das kleine Plus an gefälliger Optik handelt man sich eine erhebliche Unflexibilität beim Ändern oder Ergänzen vorhandener Diagramme ein, da sich die Reihenfolge und Plazierung der Nodes auf dem Diagramm ja jederzeit ändern kann.
    • Ein Anführungszeichen bekommen Sie mit \"


Node-Beschriftungen (Graphviz)

Beschriftung von Edges

Auch Edges lassen sich beschriften. Wollen Sie die Edge in der Mitte beschriften, dann weisen Sie ihr ein label-Attribut zu. Für Beschriftungen an der Pfeilspitze verwenden Sie ein anderes Attribut, das headlabel-Attribut. Eine Beschriftung am Ursprung der Edge erreichen Sie mit dem Atttribut taillabel.

Mit decorate=true können Sie Beschriftung und beschriftete Edge durch eine zusätzliche Linie verbinden. Ein zusätzliches labelfloat=true erlaubt dabei Überlappungen und kann zu einem kompakteren Layout führen.

Edge-Beschriftungen (Graphviz)


Alle drei Edge-Beschriftungen lassen sich kombinieren. Sie können also jede Edge theoretisch dreifach beschriften, wenn Sie für eine bestimmte Anwendung die Informationsdichte der Übersichtlichkeit vorziehen. Die Beschriftungen am Ursprung bzw. an der Spitze lasen sich separat formatieren, mit labelfontcolor, labelfontsize und labelfontname. Diese Angaben gelten aber stets sowohl für die Head- als auch für die Tail-Beschriftung.

Graphviz-labels

Unsichtbare Nodes und Edges

Übrigens ist das obige Diagramm ein schönes Beispiel für den Einsatz unsichtbarer Nodes und Edges (style=invis). Im folgenden Diagramm sind die eben noch unsichtbaren Elemente hellgrau eingezeichnet. Die unsichtbaren Elemente erzielen also die Neigung der Edge nach unten.

unsichtbare Nodes

Übersicht: Attribute für die Beschriftung

Attribut Bedeutung Default-Wert Beispiel
label Text der zentrierten Beschriftung label="Hallo!
headlabel Text der Beschriftung an der Spitze headlabel="Spitze"
taillabel Text der Beschriftung am Ursprung taillabel="Ursprung"
decorate Zusätzliche Verbindungsline zur Edge zeichnen? false decorate=true
decorate=true, labelfloat=true
fontname
labelfontname
Schriftart Times fontname=Arial
fontsize
labelfontsize
Schriftgröße 14 fontsize=12
fontcolor
labelfontcolor
Schriftfarbe black fontcolor="#41FB00"


Die verschiedenen Renderer von Graphviz

In der Sprache DOT legen Sie fest, welche Nodes es gibt, wie sie aussehen sollen, welche Beziehungen die Nodes untereinander haben und wie diese aussehen sollen. Den Rest -- insbesondere das Gesamtlayout! -- überlassen Sie dem Renderer, der aus diesen Angaben ein Diagramm zeichnet. Es gibt aber unendlich viele Möglichkeiten, aus diesen Angaben ein Diagramm zu zeichnen.

Zum Graphviz-Paket gehören verschiedene Renderer. Je nachdem, welchen Sie verwenden, wird das Ergebnis ein anderes sein:

dot

dot zeichnet streng hierarchisch strukturierte Diagramme. Die Diagramme von dot sind immer linear in eine feste Richtung aufgebaut (standardmäßig von unten nach oben). Die ersten Diagramme, die Sie in diesem Tutorial gesehen haben, sind mit dot gerendert.

neato

neato ordnet die Nodes dagegen zirkulär von der Mitte nach außen an, wie bei einer MindMap. Dazu wird simuliert, die Nodes seien physikalischen Objekte, und die Edges übten Federkräfte auf sie aus. neato versucht nun, ein Layout zu finden, in dem die Gesamtenergie des Systems möglichst gering ist.

Oft sind dies symmetrische Layouts. Die Symmetrie von neatos Diagrammen ist optisch attraktiv, vor allem aber enthält sie zusätzliche Information über Analogien, die bei anderen Darstellungsformen oft verborgen bleiben.

Um die Symmetrien möglichst klar herauszustellen, werden standardmäßig gerade Linien verwendet um die Nodes miteinander zu verbinden. dot dagegen verwendet standardmäßig Splines um den verfügbaren Platz gleichmäßiger zu nutzen. neato-Diagramme erhalten hierarchische Strukturen, d.h. Nodes auf der gleichen Hierarchiestufe sind ungefähr gleich weit vom Zentrum entfernt. In diesem Tutorial sind die Übersichten der Node-Attribute und der Edge-Attribute mit neato gerendert.

fdp

fdp erzeugt ähnliche Ergebnisse wie neato. Auch fdp liegt ein physikalisches Modell zugrunde. Bei fdp wirken aber nicht nur zwischen zwei verbundenen Nodes Kräfte. Alle Nodes stoßen einander ab und versuchen einander möglichst fern zu sein. Das führt zu Diagrammen, in denen die Nodes gleichmäßiger über die verfügbare Fläche verteilt sind als bei neato. Die gleichmäßige Verteilung geht allerdings auf Kosten der Symmetrie, wie man an den unten gezeigten Beispieldiagrammen erkennen kann. Außerdem sind hierarchische Strukturen nicht so gut erkennbar wie bei dot oder neato.

circo und twopi

Der Vollständigkeit halber seien auch circo und twopi erwähnt. Bislang ist mir noch kein Einsatzfall bekannt, in dem circo oder twopi aussagekräftigere oder schönere Diagramme zeichnen als dot, neato oder fdp. Machen Sie sich anhand der folgenden Beispieldiagramme ein eigenes Bild. circo erhält die vorhandenen hierarchischen Strukturen weitestgehend. twopi dagegen macht sie unerkennbar. Zu den Diagrammen von circo sei gesagt, dass die Standardkonfiguration der internen Parameter bei mir stets zu unbrauchbaren Ergebnissen geführt hat. Setzen Sie das Node-Attribut mindist auf einen Wert zwischen 0.5 und 0.02, um Diagramme zu erhalten, die den verfügbaren Platz sinnvoll ausnutzen. Hier hilft nur Experimentieren.

Vergleich der Renderer anhand von Beispielgrafiken

Im Folgenden können Sie die Ergebnisse der einzelnen Renderer anhand von vier Beispielgraphen direkt miteinander vergleichen. Alle Renderer erhalten stets den gleichen Graph als Input. Die meisten dieser Graphen wurden strukturell von Markus M Geipel (ETH Zurich) erstellt. Unter [8] finden Sie seine ausführliche Analyse der Darstellungskraft der verschiedenen Renderer. Zur besseren Übersicht sind die Nodes hier eingefärbt, und zwar immer auf die gleiche Weise.

Grafik scalefree grid symetric
dot
dot-Beispieldiagramm (Graphviz)

Graphviz-Beispieldiagramm mit dem Renderer dot

dot im Verleich zu neato, fdp, circo und twopi

neato
neato im Vergleich zu dot, twopi, circo und fdp

neato-Diagramm im Vergleich zu dot (Graphviz)

neato-Diagramm (Graphviz)

fdp
Graphviz fdp Beispiel

Graphviz fdp Beispieldiagramm

Graphviz-Renderer fdp Beispiel

circo
circo-Renderer Beispieldiagramm (Graphviz)

circo-Renderer Beispieldiagramm (Graphviz)

Vergleich dot neato fdp circo twopi

twopi
twopi-Renderer Beispieldiagramm (Graphviz)

Graphviz-Renderer twopi Beispiel

Graphviz-Renderer twopi Beispiel


Hilfe, mein Diagramm ist zu groß!

Es gibt verschiedene Möglichkeiten, dafür zu sorgen, dass ein Diagramm nur soviel Raum einnimmt, wie es soll. Leider: Am Schönsten wäre es ja, wenn das alles automatisch funktionieren würde. Aber wenn Sie die kritischen Parameter kennen, an denen Sie drehen müssen, ist es ganz einfach. Ich beschreibe diese Parameter jetzt im Detail. Die abschließende Übersicht der Layout-Parameter fasst noch einmal tabellarisch zusammen, welchen Parameter Sie in welchem Renderer zur Optimierung der Diagrammgröße verwenden können.

size

Zuallererst können Sie den Platz beschränken, den ein Diagramm einnehmen kann. Dazu dient der Parameter size. size ein Attribut des Graphen und legt die maximale Größe des Diagrammes fest. Die kleinen quadratischen Diagramme im Abschnitt Graphviz-Renderer sind z.B. mit folgender Einstellung entstanden:

graph [size="3, 3"]

Die maximale Größe wird in Inches angegeben, erst die Breite und dann die Höhe. Die meisten größeren Diagramme auf dieser Seite haben folgende size-Einstellung:

graph [size="10.3, 5.3"] 

Diese Größe würde einen 1024er-Bildschirm komplett ausnutzen. Der Parameter hat aber überhaupt erst dann eine Wirkung, wenn das Diagramm die maximale Größe zu überschreiten droht. In diesem Fall wird das Diagramm einfach so weit verkleinert, bis es passt. Optisch bedeutet das: Alle Nodes werden kleiner, alle Schriften werden kleiner. Das ist besser, als wenn der Betrachter das Diagramm nicht mehr in einem Stück sehen kann, aber gut ist das auch nicht.

ranksep

Beispiel für Graphviz-Attribut ranksep
ranksep=0.5 (Default)

Beispiel für Graphviz-Attribut ranksep
ranksep=0.25

Wenn Sie dot als Renderer verwenden, können Sie die Abstände zwischen den hierarchischen Rängen verkleinern. Dazu verwenden Sie den Parameter ranksep. ranksep ist ein Attribut des Graphen und wird in Inches angegeben. Die beiden Beispieldiagramme illustrieren die Wirkung von ranksep.

ranksep funktioniert ähnlich auch beim Renderer twopi. Wenn Sie diesen Renderer verwenden sollten, müssen Sie ranksep fast immer explizit angeben, da der Standardwert von twopi (ranksep=1.0) oft zu groß ist.


nodesep

Graphviz-Diagramm Attribut nodesep
Mit Angabe von nodesep=0.05

Graphviz-Diagramm Attribut nodesep
Ohne Angabe von nodesep

Wenn Sie dot als Renderer verwenden, können Sie auch die Abstände zwischen hierarchisch gleichgestellten Nodes verändern. Hierzu setzen Sie das Attribut nodesep des Graphen. In neato oder einem anderen Renderer funktioniert dies aber nicht.

Betrachten Sie das Beispiel links. Auch hier wurde die Größe ist mit size="3,3" festgelegt, und dot hat das Diagramm übermäßig verkleinert. Durch die Angabe von nodesep=0.05 müssen die Nodes nicht mehr verkleinert werden und das Diagramm passt in die angegebene Maximalgröße. Vergleichen Sie die horizontalen Abstände zwischen den Nodes bzw. ihr Verhältnis zur Größe der Nodes.


len

Graphviz-Attribut len
Mit Angabe von len=0.5

Graphviz-Attribut len
Ohne Angabe von len

Der Parameter len hat für neato und fdp eine ähnliche Wirkung wie ranksep und nodesep für dot oder twopi, wenn Sie ihn global für alle Edges festlegen. Beachten Sie bitte, dass dieses Attribut anders als die anderen Attribute ein Edge-Attribut ist. Sie können den Standardwert wie folgt festlegen:

edge [len=0.5]

Wenn Sie mit neato rendern, müssen Sie len fast immer explizit angeben, da der Standardwert von neato (1 Inch) meist zu groß ist.


mindist

mindist-Attribut (Graphviz)
Mit Angabe von mindist=0.01

mindist-Attribut (Graphviz)
Ohne Angabe von mindist: Nicht zu erkennen

Falls Sie auch mit circo rendern wollen, stellen Sie den Parameter mindist ein. Circo geht standardmäßig sehr verschwenderisch mit dem verfügbaren Platz um.

Oft enthalten Circo-Diagramme so viel freien Raum, dass man die Nodes und Edges darin kaum sehen kann. Ein Beispiel ist das Diagramm links. Nur wenn Sie genau hinschauen, können Sie einige blaue Punkte erkennen.

Mit dem Graph-Attribut mindist können Sie das Diagramm etwas verbessern. Der Wert muss recht feinfühlig eingestellt werden, auf Werte zwischen 0.5 und 0.01. Je mehr Nodes Ihr Diagramm enthält, desto kleiner muss mindist sein.

Der Defaultwert ist 1.0. Das Diagramm links, auf dem nur ein wenig blauer Dreck zu sehen ist, verwendet übrigens schon mindist=0.5, damit Sie überhaupt etwas sehen. Andernfalls wäre das Diagramm komplett weiß bis auf einen einzigen Pixel.


ratio

ratio-Attribut (Graphviz)
Mit Angabe von ratio=1.5

ratio-Attribut (Graphviz)
Ohne Angabe von ratio

Wollen Sie ein Diagramm horizontal verbreitern oder vertikal verlängern, dann funktioniert das am einfachsten und mit allen Renderern über die Angabe von ratio. Mit diesem Parameter teilen Sie dem Renderer das gewünschte Seitenverhältnis mit. Die Beispieldiagramme links und rechts sollen dies illustrieren. Im linken Diagramm ist nodesep extrem klein gewählt, so dass das Ergebnis etwas schlapp aussieht. Man könnte das mit einem größeren Wert von nodesep korrigieren, aber dann ist das Seitenverhältnis abhängig von der Diagrammstruktur. Im rechten Diagramm wird daher mit ratio=1.5 das gewünschte Seitenverhältnis angegeben und ein besseres Ergebnis erzielt.

Bei einer Angabe von ratio=2 erhalten Sie ein Diagramm mit dem Seitenverhältnis 1:2 im Hochformat. Wünschen Sie ein Seitenverhältnis von 2:1 im Querformat, dann geben Sie ratio=0.5 an. Die Angabe von ratio erzwingt das gewünschte Seitenverhältnis. Notfalls werden auch die Nodes inkl. ihrer Beschriftungen verkleinert um das gewünschte Seitenverhältnis zu erzielen.


start

Graphviz start-Attribut
start=7

Graphviz start-Attribut
start=2

Für neato und fdp gibt es ein Graph-Attribut namens start. Wenn Ihnen das Layout eines Diagrammes nicht gefällt, setzen Sie einfach dieses Attribut. Für unterschiedliche Werte von start erhalten Sie unterschiedliche Diagramme. Vor allem bei fdp sind die Ergebnisse höchst unterschiedlich. Manchmal muss man einige Werte durchprobieren, bis man ein schönes Layout erzielt.


Übersicht Layout-Parameter

Die folgende Übersicht zeigt, welchen Parameter Sie in welchem Renderer zur Optimierung der Diagrammgröße verwenden können. Sie können die Spalten mit zwei Klicks auf den gewünschten Renderer sortieren. Je mehr Kreuzchen (xxx), desto wichtiger ist der Parameter.

Parameter Bedeutung dot neato fdp circo twopi Default-Wert Beispiel-Werte
size Maximale Größe des Diagrammes.
Breite, Höhe in Inches.
xx xx xx xx xx -- "3,3" (klein)
"10.3,5.3" (passt auf 1024er Bildschirm)
ranksep Abstand zwischen den hierarchischen Rängen x xxx 0.5 (dot)
1.0 (twopi)
0.1 (winzig)
0.6 (groß)
nodesep Minimaler Abstand zwischen zwei hierarchisch gleichgestellten Nodes x 0.25 nodesep=0.05 (winzig)
len Bevorzugte Edge-Länge
Dies ist ein Edge-Attribut! Siehe Parameter len
xxx x 1.0 (neato)
0.3 (fdp)
0.5
mindist Beeinflusst den Platzbedarf von Circos Diagrammen xxx 0.5 (wenige Nodes)
0.01 (viele Nodes)
ratio Gewünschtes Seitenverhältnis x x x x x -- 2 (Hochformat)
start Beeinflusst die zufällige Verteilung der Nodes x xxx 2
overlap Sind Überlappungen erlaubt? x xx true false (sonst fallen manchmal Edges zusammen)

Kopiervorlage

Damit man die wichtigsten Parameter nicht jedesmal wieder neu nachschlagen muss, kann man sich eine Kopiervorlage erstellen, die man bei der Erstellung neuer Diagramme verwendet. Deaktivierte Bereiche sind auskommentiert.
Dies ist meine Kopiervorlage (für Mediawiki):

<graphviz renderer='dot' caption='Titel des Diagrammes' alt='Titel des Diagrammes' position='none'>
digraph G {
    graph [size="10.3,5.3", ranksep=0.5, nodesep=0.1, overlap=false, start=1]
 /* graph [rankdir=LR] */
    node  [shape=Mrecord, color="#BBBBBB"]
 /* node  [shape="ellipse", style=filled, fillcolor="#EEEEEE", color="#EEEEEE"] */
    node  [fontname=Verdana, fontsize=12, height=0.02, width=0.02]
    edge  [color="#31CEF0", len=0.5]
    edge  [fontname=Arial, fontsize=11, fontcolor="#31CEF0"]
 
}
</graphviz>


Der Ranking-Mechanismus

digraph G {
 main -> A
 main -> B
 main -> C
}

Dem Diagramm links soll eine neue Verbindungslinie hinzugefügt werden: Eine einfache Linie zwischen den Nodes B und C. Dabei passiert etwas Unerwartetes...




Ein neuer Pfeil bringt alles durcheinander

digraph G {
 main -> A
 main -> B
 main -> C
 B -> C [dir=none, 
         color=gold, 
         style=bold]
}

Hoops! Das sieht seltsam aus. Wie kommt so ein Ergebnis zustande? Ganz einfach: Graphviz stellt alle hierarchischen Beziehungen streng dar. Zumindest ist das die Standardeinstellung. Wenn im Quelltext B -> C steht, dann wird der Node B auch hierarchisch unterhalb von Node C eingezeichnet. Das geht nur, indem eine zusätzliche Hierarchieebene dargestellt wird. Das Diagramm hat nun nicht mehr nur zwei Hierarchieebenen, sondern drei.



Beispiel für Graphviz-Attribut contraint
Mit constraint=false

digraph G {
 main -> A
 main -> B
 main -> C
 B -> C [dir=none, 
         color=gold, 
         style=bold, 
         constraint=false]
}

Hier hilft das Attribut constraint. Setzen Sie es auf false um zu verhindern, dass die Edge eine neue hierarchische Ebene einführen kann.




Weight

Es gibt noch weitere Möglichkeiten das Layout des Diagrammes zu beeinflussen. Kehren wir noch einmal zurück zu dem ersten Beispiel. Wie können Sie erreichen, dass die direkte Abfolge der Nodes main, parse, execute und compare grafisch unterstrichen wird?


digraph G {
 main -> parse -> execute
 main -> init
 main -> cleanup
 execute -> make_string
 execute -> printf
 init -> make_string
 main -> printf
 execute -> compare
}
Graphviz-Diagramm ohne weight-Attribut
Das ursprüngliche Diagramm


Ganz einfach. Sie geben den Verbindungslinien zwischen diesen Nodes ein stärkeres Gewicht. Das Gewicht einer Edge wird mit dem Attribut weight festgelegt. Je größer das Gewicht, desto kürzer, gerader und vertikaler wird eine Edge dargestellt.


digraph G {
 main -> parse -> execute [weight=8]
 main -> init
 main -> cleanup
 execute -> make_string
 execute -> printf
 init -> make_string
 main -> printf
 execute -> compare [weight=8]
}
Beispiel für Graphviz-Attribut weight
Hauptpfad mit weight gekennzeichnet


Im folgenden Diagramm ist ein anderer Hauptpfad gewählt.


digraph G {
 main -> parse -> execute [weight=8]
 main -> init
 main -> cleanup
 execute -> make_string [weight=8]
 execute -> printf
 init -> make_string
 main -> printf
 execute -> compare
}
Beispiel für Graphviz-Attribut weight
Ein anderer Hauptpfad



Web-Links






Dieser Artikel ist ein Originalartikel von 4webmaster.de. Copyright: Björn Klippstein; CC-Lizensierung in Kürze