NOTE

dot

Notes on the DOT language and Graphviz: graphs, nodes, edges, attributes, subgraphs, ports, and example diagrams.

Software Architecture & Engineering1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. DOT Language

1.1. Three Elements

  • Graph
    • Define it with graph or digraph
  • Node
    • A variable name represents a node
  • Edge
    • Define it with -- or ->

1.2. Comments

  • Use // or /**/

1.3. Statements

  • Separate statements with ;

1.4. Attributes

  • Use [key=value, key1=value1, key3="value3, value4"]

2. Graphs

2.1. Definition

2.1.1. Directed Graph

// undirected graph
graph simple {
    a--b--c;
    b--d;
}

2.1.2. Undirected Graph

// directed graph
digraph simple {
    a->b->c;
    b->d;
}

2.2. Graph Attributes

digraph graph_attr {
    graph [bgcolor = "#666666",
    fontname="Futura", fontcolor = white, fontsize = 24,
    labelloc = t, labeljust = c]

    label = "Graphviz\nGraph Drawing Scripting Tool"
    node0->node1;
}

2.3. Subgraphs

  • Define a subgraph with subgraph; name it cluster_xxx
  • A subgraph inherits attributes from its parent graph, but can override them locally without affecting the parent or sibling subgraphs
  • In Graphviz, relationships normally exist only between nodes. To connect nodes or subgraphs at the cluster level, set compound=true on the parent graph and use lhead and ltail on edges
digraph g {
    graph[compound=true]
    node1->a;
    
    subgraph cluster_c1 {
        a->b;
    }
    subgraph cluster_c2 {
        c->d;
    }
    
    edge [dir=none]
    node1->c[lhead=cluster_c2, label="test"];
}

3. Nodes

3.1. Definition

3.1.1. Regular Nodes

digraph node_define {
    name1;
    name2;
}

3.1.2. Record Nodes

digraph g {
    node [shape=record, width=.1, height=.1];
    
    // left node: two fields with field IDs
    node0[label="<f0> \<=333|<f1> \>333"]
    // right node: three fields with field IDs
    node1 [label="{<n> 111|222|<p> 333}"]
    node2 [label="{<n> 444|555|<p> 666}"]

    node0:f0->node1:n;
    node0:f1->node2:p;
}

3.2. Node Attributes

3.2.1. Global

digraph node_attr {
    node[shape=box, label="test"]
    a1->a2;
}

3.2.2. Local

digraph node_attr {
    shape1 [shape=box, label="shape1" style="filled", fillcolor="#73819F"];
    shape2 [shape=box, label="shape2"];
    shape1->shape2;
}

3.3. Ports

  • A node has eight ports for connections: n, ne, e, se, s, sw, w, and nw
digraph graphNodePorts {
  a -> b [tailport=w];
  c:sw -> b:e;
}
graph g {
    a--b;
    a--c;
}

4. Edges

4.1. Definition

4.1.1. Directed

digraph g {
    a->b;
    b->c;
}

4.1.2. Undirected

graph g {
    a--b;
    b--c;
}

4.2. Edge Attributes

4.2.1. Global

digraph edge_attr{
    edge[style="bold solid", color="red", label="bold red"]
    a1->a2;
}

4.2.2. Local

digraph edge_attr {
    style0->style1[style=solid, label="solid line"]
    style1->style2[style=bold, label="solid line"]
}

5. Examples

5.1. binary search tree

digraph g {
    node [shape=record, height=.1];
    node0[label="<f0> |<f1> 1 |<f2> "];
    node1[label="<f0> |<f1> 2 |<f2> "];
    node2[label="<f0> |<f1> 3 |<f2> "];
    node3[label="<f0> |<f1> 4 |<f2> "];
    node4[label="<f0> |<f1> 5 |<f2> "];
    node0:f0 -> node1:f1;
    node0:f2 -> node2:f2;
    node2:f0 -> node3:f2;
    node2:f2 -> node4:f2;
}

5.2. hash table

digraph G {
    // spacing
    nodesep=.05;
    // left-to-right layout
    rankdir=LR;
    // node attributes
    node [shape=record, width=.1, height=.1];
    
    // left node: two fields with field IDs
    node0[label="<f0>|<f1>"]
    // right node: three fields with field IDs
    node1 [label="{<n> 111|222|<p> 333}"]
    node2 [label="{<n> 444|555|<p> 666}"]

    node0:f0->node1:n;
    node0:f1->node2:p;
}

5.3. Face Recognition

strict digraph g1 {
    // graph attributes
    graph [bgcolor = "white", fontname="Arial", 
        fontcolor = black, fontsize = 18, splines=false,
        nodesep=1.5, ranksep=1.5, rankdir=TB, label="Face Recognition"];
    // node attributes
    node[fontname="Arial", fontsize = 18, 
        shape="box", style="rounded"]
    // edge attributes
    edge[fontname="Arial", fontsize = 12]

    // subgraph: define nodes and layout placeholders
    subgraph cluster_level {
        graph[label="Layers"];
        node [shape=plaintext, fontname="Arial", fontsize=16];
        edge [style=invis];
        // define nodes
        l1[label="client layer"];
        l2[label="server layer"];
        l3[label="basic_server layer"];
        l4[label="storage layer"];
        // edges
        l1 -> l2 -> l3 -> l4;
    }

    subgraph cluster_txy {
        graph[label="Cloud Provider"];
        // define nodes
        n5[label="Face Verification\nService"];
        node [shape=plaintext, fontname="Arial", fontsize=16];
        edge [style=invis];
        t1[label=""];
        t2[label=""];
        t3[label=""];
        // edges
        t1->n5->t2->t3;
    }

    subgraph cluster_txzb {
        graph[label="Business System"];
        // define nodes
        n1[label="Business\nApp"]
        n2[label="Operations\nPlatform"]
        n3[label="Identity Verification\nService"]
        n4[label="Identity Admin\nService"]
        n6[label="Shared Identity\nService"]
        n7[label="MySQL"]
        // edges
        n1->n3[label="1 Get SDK startup parameters\n4 Server verifies the result"];
        n1->n5[label="3 Start SDK and upload verification data"];
        n3->n5[label="2 Get SDK startup parameters\n5 Query verification result"];
        n3->n6[label="7 Update identity data after success"];
        n3->n7[label="6 Write identity data to the database"];
        n2->n4[label="1 Manual approve/reject"];
        n4->n6[label="2 Update identity data after approval"];
        n4->n7[label="3 Update database"];
    }


    // group: same row
    {rank = same; l1;t1;n1;n2;}
    {rank = same; l2;n3;n4;n5;}
    {rank = same; l3;t2;n6;}
    {rank = same; l4;t3;n7;}


}

5.4. General

strict digraph g1{
    // graph attributes
    graph [fontname="Arial", fontsize = 18, splines=false,
        nodesep=1.5, ranksep=1.5,  label="Test"];
    // node attributes
    node[fontname="Arial", fontsize = 18, 
        shape="box", style="rounded"]
    // edge attributes
    edge[fontname="Arial", fontsize = 12]

    // subgraph: logical/edge grouping
    subgraph cluster_level {
        graph[label="Level"];
        node [shape=plaintext];
        edge [style=invis];
        
        l1[label="client layer"];
        l2[label="service layer"];
        l3[label="basic_service layer"];
        l4[label="storage layer"];
        l1->l2->l3->l4;
    }
    subgraph cluster_outer {
        graph[label="Outer"];
        edge [style=invis];

        o1[label="",shape=plaintext];
        o2[label="External Service"];
        o3[label="",shape=plaintext];
        o4[label="",shape=plaintext];
        o1->o2->o3->o4;
    }
    subgraph cluster_inner {
        graph[label="Inner"];

        i1[label="client1"];
        i2[label="client2"];
        i3[label="Aggregation Service 1"];
        i4[label="Aggregation Service 2"];
        i5[label="Basic Service"];
        i6[label="Storage"];
        i1->o2;
        i1->i3->{i5,i6,o2};
        i2->i4->{i5,i6};
    }
    // layout: same row
    {rank=same;l1;o1;i1;i2;}
    {rank=same;l2;o2;i3;i4;}
    {rank=same;l3;o3;i5;}
    {rank=same;l4;o4;i6;}
    
}

6. References

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub