├── README.md └── README_img ├── edge_node_attributes.png ├── not_ordered.png ├── ordered_invis.png ├── ordered_vis.png ├── pngquality_dpi100.png ├── pngquality_dpi20.png ├── rank_min_max.png ├── rank_ranksep.png ├── rankdir_LR.png ├── rankdir_default.png ├── rankdir_shifted.png ├── splines_default.png ├── splines_ortho.png ├── squeezed.png ├── temp.png ├── tricked_invis.png └── tricked_vis.png /README.md: -------------------------------------------------------------------------------- 1 | # Dumpy 2 | This repo describes some useful patterns and tips in GraphVIZ for creating graphical dumps. 3 | # GraphVIZ 4 | Graphviz is open source graph visualization software. It can be used for creating graphs from text file with special description. See more details on https://graphviz.org. 5 | 6 | First steps and basic ideas can be found here: http://lib.custis.ru/Graphviz. 7 | 8 | **Most of the attributes are described very briefly or not mentioned because they are easy to find in official documentation. But some patterns are not explicitly described on official site, nor on side sources. That's why that reference was created.** 9 | ___ 10 | ___ 11 | ## Attributes 12 | ### ***Quality of image*** 13 | First of all, quality of **.png** can be very poor. Use **`dpi`** attribute (Dots Per Inch) or **.svg** format (vector graphics) instead of **.png**. 14 | 15 | Examples: 16 | 17 | dpi = 100: 18 | 19 | 20 | 21 | dpi = 20: 22 | 23 | 24 | 25 | Example of code: 26 | 27 | digraph G 28 | { 29 | graph [dpi = 20]; 30 | 31 | example_node1[label = "Hello, World!"]; 32 | example_node2[label = "Yet Another 'Hello, World!'"]; 33 | 34 | example_node1 -> example_node2 [color = "red"] 35 | } 36 | 37 | ___ 38 | ### ***Ranks*** 39 | Same rank of nodes means that nodes are on the same line. 40 | 41 | *In GraphVIZ system of ranks is a stable way to layout nodes in one line.* 42 | 43 | **`rank`** --- attribute to set rank of node(s) 44 | (Valid values: `same` (set nodes on the same rank), `min` (set nodes on the minimal rank), `max` (set nodes on the maximal rank)). 45 | 46 | **`ranksep`** --- attribute to set distance between ranks (inches) 47 | 48 | Example of code: 49 | 50 | 51 | digraph G 52 | { 53 | graph [dpi = 100]; 54 | 55 | {rank = min; 56 | above_other_nodes[label = "I'm high"]; 57 | } 58 | 59 | {rank = same; 60 | example_node1[label = "Hello, World!"]; 61 | example_node2[label = "Yet Another 'Hello, World!'"]; 62 | example_node3[label = "And Another 'Hello, World!'?!"]; 63 | example_node4[label = "Not 'Hello, World!'"]; 64 | } 65 | 66 | {rank = max; 67 | below_other_nodes[label = "I'm low, u know"]; 68 | } 69 | 70 | example_node2 -> below_other_nodes [color = "green"]; 71 | 72 | example_node1 -> example_node2 -> example_node4 [color = "red"]; 73 | example_node1 -> example_node3 [color = "red"]; 74 | example_node2 -> example_node3 [color = "red"]; 75 | 76 | example_node2 -> above_other_nodes [color = "blue"]; 77 | 78 | } 79 | 80 | 81 | 82 | Adding `ranksep = 1.5`: 83 | 84 | digraph G 85 | { 86 | graph [dpi = 100]; 87 | 88 | ranksep = 1.5; 89 | 90 | {rank = min; 91 | above_other_nodes[label = "I'm high"]; 92 | } 93 | 94 | {rank = same; 95 | example_node1[label = "Hello, World!"]; 96 | example_node2[label = "Yet Another 'Hello, World!'"]; 97 | example_node3[label = "And Another 'Hello, World!'?!"]; 98 | example_node4[label = "Not 'Hello, World!'"]; 99 | } 100 | 101 | {rank = max; 102 | below_other_nodes[label = "I'm low, u know"]; 103 | } 104 | 105 | example_node2 -> below_other_nodes [color = "green"]; 106 | 107 | example_node1 -> example_node2 -> example_node4 [color = "red"]; 108 | example_node1 -> example_node3 [color = "red"]; 109 | example_node2 -> example_node3 [color = "red"]; 110 | 111 | example_node2 -> above_other_nodes [color = "blue"]; 112 | 113 | } 114 | 115 | 116 | 117 | 118 | ___ 119 | ### ***Splines*** 120 | The standard style of edges in GraphVIZ is very hard to control, but you can use **`splines`** attribute to change it. Tips given below are working nice with **`splines = ortho`**. 121 | 122 | Default splines (without `splines` attribute) 123 | 124 | 125 | 126 | `splines = ortho`: 127 | 128 | 129 | 130 | Example of code: 131 | 132 | 133 | 134 | digraph G 135 | { 136 | graph [dpi = 100]; 137 | splines = ortho 138 | 139 | {rank = same; 140 | example_node1[label = "Hello, World!"]; 141 | example_node2[label = "Yet Another 'Hello, World!'"]; 142 | example_node3[label = "And Another 'Hello, World!'?!"]; 143 | example_node4[label = "Not 'Hello, World!'"]; 144 | } 145 | 146 | example_node1 -> example_node2 -> example_node4 [color = "red"]; 147 | example_node1 -> example_node3 [color = "red"]; 148 | example_node2 -> example_node3 [color = "red"]; 149 | } 150 | ___ 151 | ### ***Edge attributes*** 152 | **`minlen`** --- minimal length of edge (inches) 153 | 154 | **`penwidth`** --- width of edge (pixels) 155 | 156 | **`weight`** --- edge priority (attribute adds 'weight' to arrow, so GraphVIZ will try to make it as short as possible) 157 | 158 | **`dir`** --- edge direction 159 | 160 | ### ***Node attributes*** 161 | *Note that if you want to set two same attributes you should write both of them in `""` (Example: `style = "rounded, filled"`)* 162 | 163 | **`shape`** --- shape of node 164 | 165 | **`style`** --- style of node (recommended value: roun**ded**) 166 | 167 | **`height`, `width`** --- maximal height and width of node in inches (**use with 168 | `fixedsize = true` to set fixed size of node**) 169 | 170 | **`penwidth`** --- width of node border 171 | 172 | Example of code: 173 | 174 | digraph G 175 | { 176 | graph [dpi = 100]; 177 | splines = ortho 178 | 179 | bgcolor = "#2F353B" 180 | 181 | edge[minlen = 3, penwidth = 3; color = "green"]; 182 | node[shape = "rectangle", style = "rounded, filled", 183 | height = 3, width = 2.3, fixedsize = true, 184 | fillcolor = "#00b899", 185 | fontsize = 30, 186 | penwidth = 5, color = "yellow" 187 | ] 188 | 189 | {rank = same; 190 | example_node1[label = "HW!"]; 191 | example_node2[label = "YAHW"]; 192 | example_node3[label = "AAHW?!"]; 193 | example_node4[label = "NHW"]; 194 | } 195 | 196 | example_node1 -> example_node2 -> example_node4 [color = "red"]; 197 | example_node1 -> example_node3 [color = "red"]; 198 | example_node2 -> example_node3 [color = "red"]; 199 | } 200 | 201 | 202 | 203 | ___ 204 | ___ 205 | ## Tips 206 | ### ***Powerful*** `style = invis` 207 | It's very powerful architechture tool to create nice graphs. Can be used for edges and nodes. Examples of usage below. 208 | ___ 209 | ### ***Ordered layout*** 210 | To create ordered layout you can use edge's attribute `weight` and `style = invis` to create 'heavy' invisible edges. They bind nodes in needed order. 211 | 212 | Example of code: 213 | 214 | digraph G 215 | { 216 | graph [dpi = 100]; 217 | splines = ortho 218 | 219 | edge[minlen = 3, penwidth = 3]; 220 | node[shape = rectangle, style = rounded, fixedsize = true, 221 | height = 3, width = 2, fontsize = 30]; 222 | 223 | {rank = same; 224 | node1[label = "1"]; 225 | node2[label = "2"]; 226 | node3[label = "3"]; 227 | node4[label = "4"]; 228 | node5[label = "5"]; 229 | node6[label = "6"]; 230 | node7[label = "7"]; 231 | } 232 | 233 | node1 -> node7 [color = "green"]; 234 | node3 -> node1 [color = "green"]; 235 | node2 -> node6 [color = "green"]; 236 | node3 -> node6 [color = "green"]; 237 | node4 -> node2 [color = "green"]; 238 | } 239 | 240 | 241 | 242 | Add 'heavy' arrows: 243 | 244 | ... 245 | 246 | node1 -> node2 -> node3 -> node4 [weight = 5]; 247 | node4 -> node5 [weight = 5]; 248 | node5 -> node6 [weight = 5]; 249 | node6 -> node7 [weight = 5]; 250 | ... 251 | 252 | 253 | 254 | Add `style = invis` 255 | 256 | ... 257 | 258 | node1 -> node2 -> node3 -> node4 [weight = 5, style = invis]; 259 | node4 -> node5 [weight = 5, style = invis]; 260 | node5 -> node6 [weight = 5, style = invis]; 261 | node6 -> node7 [weight = 5, style = invis]; 262 | ... 263 | 264 | 265 | 266 | ___ 267 | ### ***Horizontal layout*** 268 | We can use graph's attribute `rankdir` to set horizontal layout, but this layout isn't stable when you create edges. 269 | 270 | digraph G 271 | { 272 | graph [dpi = 100]; 273 | 274 | edge[minlen = 3, penwidth = 3]; 275 | node[shape = rectangle, style = rounded, fixedsize = true, 276 | height = 3, width = 2, fontsize = 30]; 277 | 278 | node1[label = "1"]; 279 | node2[label = "2"]; 280 | node3[label = "3"]; 281 | 282 | node1 -> node2 -> node3; 283 | } 284 | 285 | Default layout: 286 | 287 | 288 | 289 | With `rankdir = LR;`: 290 | 291 | 292 | 293 | Add `node1 -> node3`: 294 | 295 | 296 | 297 | but you can use `weight` attribute (see ***Ordered layout***) to fix nodes positions. 298 | 299 | Another way is to use `rank = same` for nodes (see ***Ranks***), which explicitly says that nodes should have the same rank on the picture. This variant is stable, so recommended. 300 | ___ 301 | ### ***shape*** `record` 302 | `rank = same` is broken for node's attribute `shape = record`, which is very suitable for dump information. The problem appears if you try to create edges between adjacent nodes. There are two solutions: 303 | 1. Not to use `record`'s as buggy shape. 304 | 2. Use `splines = ortho` with records. 305 | ___ 306 | ### ***How to set distance between edges*** 307 | There is *no* way to set distance explicitly. So we have to use a trick. 308 | 309 | We create two nodes (let's call them base nodes) with `style = invis` on `rank = min` and `rank = max`, then create *our* nodes on `rank = same` and connect our first node to each of base nodes. We set graph attribute `ranksep = 1.5`. That way we explicitly create space above and below *our* nodes and GraphVIZ won't squeeze picture vertically. 310 | 311 | Without a trick: 312 | 313 | 314 | 315 | With a visible trick: 316 | 317 | 318 | 319 | With an invisible trick: 320 | 321 | 322 | 323 | Example of code (see and *understand* ***Ranks*** to create invisible trick): 324 | 325 | digraph G 326 | { 327 | graph [dpi = 100]; 328 | 329 | ranksep = 1.5; 330 | 331 | splines = ortho 332 | 333 | edge[minlen = 3, penwidth = 3]; 334 | node[shape = record, style = rounded, 335 | fixedsize = true, height = 1, width = 2, 336 | fontsize = 30]; 337 | 338 | {rank = min; 339 | above_node[label = "I'm disappearing", width = 3]; 340 | } 341 | {rank = same; 342 | node1[label = "1"]; 343 | node2[label = "2"]; 344 | node3[label = "3"]; 345 | node4[label = "4"]; 346 | node5[label = "5"]; 347 | node6[label = "6"]; 348 | } 349 | {rank = max; 350 | below_node[label = "Don't look at me", width = 3]; 351 | } 352 | 353 | above_node -> node1; 354 | below_node -> node1; 355 | 356 | node1 -> node2 -> node3 [weight = 5; style = invis]; 357 | node3 -> node4 -> node5 [weight = 5; style = invis]; 358 | node5 -> node6 [weight = 5, style = invis]; 359 | 360 | node1 -> node3; 361 | node5 -> node2; 362 | node1 -> node6; 363 | node1 -> node4; 364 | node3 -> node5; 365 | } 366 | -------------------------------------------------------------------------------- /README_img/edge_node_attributes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/edge_node_attributes.png -------------------------------------------------------------------------------- /README_img/not_ordered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/not_ordered.png -------------------------------------------------------------------------------- /README_img/ordered_invis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/ordered_invis.png -------------------------------------------------------------------------------- /README_img/ordered_vis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/ordered_vis.png -------------------------------------------------------------------------------- /README_img/pngquality_dpi100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/pngquality_dpi100.png -------------------------------------------------------------------------------- /README_img/pngquality_dpi20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/pngquality_dpi20.png -------------------------------------------------------------------------------- /README_img/rank_min_max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/rank_min_max.png -------------------------------------------------------------------------------- /README_img/rank_ranksep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/rank_ranksep.png -------------------------------------------------------------------------------- /README_img/rankdir_LR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/rankdir_LR.png -------------------------------------------------------------------------------- /README_img/rankdir_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/rankdir_default.png -------------------------------------------------------------------------------- /README_img/rankdir_shifted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/rankdir_shifted.png -------------------------------------------------------------------------------- /README_img/splines_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/splines_default.png -------------------------------------------------------------------------------- /README_img/splines_ortho.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/splines_ortho.png -------------------------------------------------------------------------------- /README_img/squeezed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/squeezed.png -------------------------------------------------------------------------------- /README_img/temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/temp.png -------------------------------------------------------------------------------- /README_img/tricked_invis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/tricked_invis.png -------------------------------------------------------------------------------- /README_img/tricked_vis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/futherus/dumpy/ddcda8370b8d01260e3488541e65b8dbac705cf4/README_img/tricked_vis.png --------------------------------------------------------------------------------