how to avoid overlapping edge and node when using graphviz? - graphviz

As title,I want to draw an image of ELF file format.The ELF Header has offset of program headers table and section headers table,so I want to use two arrows pointer to point out the relationship.But the edges overlap the node(record) even after I have overlap=false and splines=true set.I have search for a while,but my situation is that the arrows somewhat point to parts of itself.
Following is the dot file I am using to generate the png file.
digraph g {
//margin="1"
overlap='scale'
graph [rankdir="LR"]
"ELF File" [
label="<f0> ELF Header\n e_shoff=0x118| <f1> Program Headers Table | <f2> .text | <f3> .data | <f4> .rodata| <f5> .comment | <f6> .shstrtab | <f8> .symtab | <f9> .rel.text | <f7> Section Table"
shape="record"
];
"ELF File":f0 -> "ELF File":f1 [label="e_phoffset"]
"ELF File":f0 -> "ELF File":f7 [label="e_shoff"]
}

One possible solution is to use "east" node ports on one of the edges, so that this edge appears on opposite side of the record. You do this by appending :e to the node name. For example:
"ELF File":f0:e -> "ELF File":f7:e [label="e_shoff"]

Related

Set pre-defined node styles?

I've been googling around for the last 15 minutes trying to find an answer to this. But I can't seem to figure it out.
I was tasked with building some small flowcharts for some applications I've developed at work. They don't need anything fancy because they are going to convert it into their preferred format in vizio. They even said we could do it pen and paper. So I figured I would play around with graphviz/dot.
They have 6 pre-defined shapes/colors that they like to use, so I figured I would use them. I've already built them all in dot...but if I plan to re-use them many times, I'd like to find a way to save them as a sort of template.
Is that possible?
For example...These are the predefined shapes.
digraph G {
node [color="#4271C6"]
process [
shape=Mrecord,
style=filled, fillcolor="#E1F4FF",
label="{1. Process\l | Description}"];
subprocess [
shape=record,
style=filled, color="#FFFFFF", fillcolor="#A5A5A5",
label="| Sub-Process |"];
database [
shape=cylinder, color="#18589A",
label="Database"];
inputoutput [
shape=polygon,
style=filled, fontcolor=white,
fixedsize=true, skew=0.3, margin=0,
width=2, label="Input / Output"];
file [
shape=folder,
label="File"];
external [
shape=box3d,
label="External entity"];
}
unfortunately there is no way to define macros or objects and reuse - especially across multiple graphs. However there are ways using other tools. Some folks use m4 (the macro language) or cpp (the C pre-processor) Both work, but there are potential OS issues. Python, awk, ... would also work.
Here is a gvpr program (gvpr is part of the Graphviz package) that also does what you want (I think):
digraph pre{
a [_type=process label="{1. Process\l | Something}"]
b [_type=process label="{2. Process\l | Something else}"]
c [_type=subprocess label="do it"]
d [_type=database label="lots of data"]
e [_type=database label="a bit of data"]
f [_type=inputoutput label="inOut"]
g [_type=file label="nail file"]
h [_type=external label="outside"]
a->b->c->d->e->f->g->h
}
The gvpr program:
BEG_G{
$G.newrank="true";
}
N{
$.color="#4271C6"; // default
}
N[_type=="process"]{
$.shape="Mrecord";
$.style="filled";
$.fillcolor="#E1F4FF";
// maybe redo $.label
}
N[_type=="subprocess"]{
$.shape="record";
$.style="filled";
$.color="#FFFFFF";
$.fillcolor="#A5A5A5";
$.label=sprintf("|%s|", $.label); // embed in pipes
}
N[_type=="database"]{
$.shape="cylinder";
$.color="#18589A";
}
N[_type=="inputoutput"]{
$.shape="polygon";
$.style='filled';
$.fontcolor="white",
$.ixedsize="true";
$.skew="0.3";
$.margin="0";
$.width="2";
}
N[_type=="file"]{
$.shape="folder";
}
N[_type=="external"]{
$.shape="box3d";
}
Produces:
There may currently be problems with gvpr on Windows, but I know the development team is working on it
Here is the command line:
gvpr -c -f predefined.gvpr predefined2.gv | dot -Tpng > predefined2.png
Okay, so I figured it out. I didn't realize you could do this...but apparently you can break up a node definition into multiple parts...so this is what I came up with, which solves my problem...
I have a "Styles" section that goes at the top. Here I can define each node style. I use comments as a way of naming them. And I don't need to copy paste, because I can just define multiple nodes as a comma separated list.
I also found that you can put them into subgraphs as well, like subgraph style_file {...}. But it seemed simpler to just use a comment as a way to name the style.
digraph G {
newrank=true;
///////////////////////////////////////////////////////////
// Styles
///////////////////////////////////////////////////////////
node [color="#4271C6"];
edge [color="#4271C6"];
//process
createfile, uploadfile
[shape=Mrecord, style=filled, fillcolor="#E1F4FF"];
//subprocess
exportfile, wait
[shape=record, style=filled, color="#FFFFFF", fillcolor="#A5A5A5"];
//external
ftp
[shape=box3d];
//datastore
database
[shape=cylinder, color="#18589A"];
//io
exportproc
[shape=polygon, style=filled, fontcolor=white, margin=0, width=3.1, fixedsize=true, skew=0.3];
//file
workfile
[shape=folder];
///////////////////////////////////////////////////////////
// Clusters
///////////////////////////////////////////////////////////
subgraph cluster_0 {
createfile [label="{1. Process\l | Create file}"];
exportfile [label="|Export Data\nfrom DB|"];
database [label="Database"];
exportproc [label="Export Data"];
workfile [label="Generated file\n(Archived on server)"];
}
subgraph cluster_1 {
uploadfile [label="{2. Process\l | Upload file}"];
ftp [label="FTP Server"];
wait [label="|Wait for\nresponse file|"];
}
///////////////////////////////////////////////////////////
// Relationships
///////////////////////////////////////////////////////////
{
rank=same;
createfile;
uploadfile;
}
///////////////////////////////////////////////////////////
// Relationships
///////////////////////////////////////////////////////////
# cluster_0
createfile -> exportfile;
exportfile -> database;
database -> exportproc;
exportproc -> workfile [style=dashed];
workfile -> uploadfile;
# cluster_1
uploadfile -> ftp [style=dashed];
ftp -> wait;
}
Which produces this:
No affiliation, but the Excel to Graphviz application can create re-usable styles as can be seen in this screenshot:

How to reference/name specific part of a shape?

I want to reference a specific part of a shape. For example: From Best Apple to Basket 1, instead of apple_node to Basket 1.
The below image will better explain what I wish to achieve.
https://imgur.com/a/B0TEoWO
This is my graphviz code and what I have achieved so far:
digraph fruits {
node [shape=record]
apple_node [label="Apple | {{Best Apple} | {Worst Apple}}"];
banana_node [label="Banana | {{Best Banana} | {Worst Banana}}"];
basket1_node [label="basket1|{Colour 10 | Seeds 10}"];
basket2_node [label="basket2|{Colour 10 | Seeds 10}"];
apple_node -> basket1_node;
banana_node -> basket2_node;
}
Since you are using record-based nodes, you can add field id's to the label and use them as portnames which indicate where to attach an edge to (see also the official documentation about record-based nodes).
Example:
examplenode [shape=record; label="<fieldid1> one|<fieldid2> two"];
examplenode:fieldid1 -> othernode;
Your apple-banana example:
digraph fruits {
node [shape=record]
apple_node [label="Apple | {{<bestapple>Best Apple} | {<worstapple>Worst Apple}}"];
banana_node [label="Banana | {{Best Banana} | {<worstbanana>Worst Banana}}"];
basket1_node [label="basket1|{Colour 10 | Seeds 10}"];
basket2_node [label="basket2|{Colour 10 | Seeds 10}"];
apple_node:bestapple -> basket1_node;
apple_node:worstapple -> basket1_node;
banana_node:worstbanana -> basket2_node;
}

Html Horizontal line error graphviz

I'm needing to create subgraph cluster have a label with line separation from nodes.
subgraph cluster_0{
label=< <B>process #1</B> <HR/> >
node [shape=none]
t1 [label="label1"]
t2 [label="label2"]
t3 [label="label 3"]
node [shape=box group=a style=filled fillcolor="red;.5:white" height=.2 label = "" ]
A [ fillcolor="red;0.3:white" ]
B [fillcolor="red;.9:white"]
C
node [shape=none fillcolor=white]
t11 [label="label1"]
t21 [label="label2"]
t31 [label="label 3"]
edge[style=invis];
A->B->C
t1->t2->t3
t11->t21->t31
}
Then I get in error on Syntax.
error stack
pydot.InvocationException: Program terminated with status: 1. stderr follows: Error: syntax error in line 1
... <HR/> ...
in label of graph cluster_0
My graphviz version is
dot - graphviz version 2.36.0 (20140111.2315)
On the graphviz web site, the page called "Node Shapes" contains a grammar (about half-way down) for html-like labels:
For <HR/>, it says:
rows : row
| rows row
| rows <HR/> row
This means that <HR/> is only allowed in between two rows. And rows are only allowed within a <TABLE>, so you'll have to wrap everything in a table and then it may work.
Depending on what exactly you'd like to achieve, an other possible solution might be to simply underline the label using <U>text</U>.

Extracting plain text output from binary file

I am working with Graphchi's pagerank example: https://github.com/GraphChi/graphchi-cpp/wiki/Example-Apps#pagerank-easy
The example app writes a binary file with vertex information that I would like to read/convert to a plan text file (to later call into R or some other language).
The documentation states that:
"GraphChi will write the values of the edges in a binary file, which is easy to handle in other programs. Name of the file containing vertex values is GRAPH-NAME.4B.vout. Here "4B" refers to the vertex-value being a 4-byte type (float)."
The 'easy to handle' part is what I'm struggling with - I have experience with high level languages but not C++ or dealing with binary files. I have found a few things through searching stackoverflow but no luck yet in reading this file. Ideally this would be done through bash or python.
thanks very much for your help on this.
Update: hexdump graph-name.4B.vout | head -5 gives:
0000000 999a 3e19 7468 3e7f 7d2a 3e93 d8e0 3ec4
0000010 cec6 3fe4 d551 3f08 eff2 3e54 999a 3e19
0000020 999a 3e19 3690 3e8c 0080 3f38 9ea3 3ef5
0000030 b7d6 3f66 999a 3e19 10e3 3ee1 400c 400d
0000040 a3df 3e7c 999a 3e19 979c 3e91 5230 3f18
Here is example code how you can use GraphCHi to write the output out as a string:
https://github.com/GraphChi/graphchi-cpp/wiki/Vertex-Aggregators
But the array is simple byte array. Here is example how to read it in python:
import struct
from array import array as binarray
import sys
inputfile = sys.argv[1]
data = open(inputfile).read()
a = binarray('c')
a.fromstring(data)
s = struct.Struct("f")
l = len(a)
print "%d bytes" %l
n = l / 4
for i in xrange(0, n):
x = s.unpack_from(a, i * 4)[0]
print ("%d %f" % (i, x))
I was having the same trouble. Luckily I work with a bunch of network engineers who helped me out! On Mac Linux, the following command works to print the 4B.vout data one line per node, with the integer values the same as is given in the summary file. If your file is called eg, filename.4B.vout, then some command line perl gets you:
cat filename.4B.vout | LANG= perl -0777 -e '$,=\"\n\"; print unpack(\"L*\",<>),\"\";'
Edited to add: this is for the assignments of connected component ID and community ID, written implicitly the 1st line is the ID of the node labeled 0, the 2nd line is the node labeled 1 etc. But I am copypasting here so I'm not sure how it would need to change for floats. It works great for the integer values per node.

Pretty Printing a tree data structure in Ruby

I am working on a building a compiler and within that I generate a tree that represents the source program that is passed in. I want to display this is a tree like fashion so I can display the structure of the program to anyone interested.
Right now I just have the tree printing on a single line like this:
ProgramNode -> 'Math' BlockNode -> DeclarationNode -> ConstantDeclarationNode -> const ConstantListNode -> [m := 7, ConstantANode -> [n := StringLiteralNode -> ""TEST"" ]] ;
What I would like is something like this:
ProgramNode
/ \
'Math' BlockNode
|
DeclarationNode
|
ConstantDeclarationNode ------------------------------
/ \ |
const ConstantListNode |
/ | \ \ |
m := 7 ConstantANode |
/ | \ |
n := StringLiteralNode |
/ | \ |
" TEST " ;
I haven't really worked with trees in Ruby, how are they usually represented?
Any help would be appreciated.
This kind of pretty printing requires quite a bit of math. Besides, it's unclear what should happen if the tree grows too wide for the console window. I don't know of any existing libraries that'll do this. I personally use awesome_print.
tree = {'ConstantDeclarationNode' => ['const',
'ConstantListNode' => ['m', ':=', '7']]}
require 'awesome_print'
ap tree
# >> {
# >> "ConstantDeclarationNode" => [
# >> [0] "const",
# >> [1] {
# >> "ConstantListNode" => [
# >> [0] "m",
# >> [1] ":=",
# >> [2] "7"
# >> ]
# >> }
# >> ]
# >> }
It has tons of options, check it out!
You need to check out the Graph gem. It is amazing and remarkably simple to work with. You can choose the direction of your tree and the shape of the nodes, as well as colors and so much more. I first found out about it at Rubyconf last year and was blown away.
It is as simple as:
digraph do
edge "Programnode", "Blocknode"
edge "Programnode", "Math"
edge "Blocknode", "DeclarationNode"
end
Obviously you would want to programmatically enter the edges :)
Here is a link to a pdf of the talk which will give more information on it:
There is also a video of the talk on Confreaks if you are interested.
Cheers,
Sean

Resources