0x01 Graphviz简述
Graphviz是大名鼎鼎的贝尔实验室的几位牛人开发的一个画图工具,它提供了“所想即所得”的理念,通过dot语言来编写脚本并绘制图形,简单易懂。
摘自维基百科的资料:https://zh.wikipedia.org/wiki/Graphviz
<span style="font-size:18px;">Graphviz由一种被称为DOT语言的图形描述语言 与一组可以生成和/或处理DOT文件的工具组成:
dot
一个用来将生成的图形转换成多种输出格式的命令行工具。其输出格式包括PostScript,PDF,SVG,PNG,含注解的文本等等。
neato
用于sprint model的生成(在Mac OS版本中称为energy minimized)。
twopi
用于放射状图形的生成
circo
用于圆形图形的生成。
fdp
另一个用于生成无向图的工具。
dotty
一个用于可视化与修改图形的图形用户界面程序。</span>
0x02 Graphviz能用来做什么
如果你想做数据分析,或者可视化处理,亦或是想在编程时动态的输出流程图,Graphvizs是一个好帮手。
文字描述就不多说了,主要看下面这些图:



<span style="font-size:18px;"> 1: digraph abc{
2: node [shape="record"];
3: edge [style="dashed"];
4:
5: a [style="filled", color="black", fillcolor="chartreuse"];
6: b;
7: c;
8: d;
9:
10: a -> b;
11: b -> d;
12: c -> d [color="red"];
13: }</span>
片段代码2
<span style="font-size:18px;">strict digraph {
graph [epsilon=0.001];
a -> b;
b -> c;
}</span>
代码中定义边的长度 颜色 由哪个点到哪个点就可以绘制简单的图形了。如果还嫌麻烦,python 对graphviz 进行了一次封装 使用pygraphviz就可以在python里面直接绘图啦,灰常贴心。
<span style="font-size:18px;">import pygraphviz as pgv
A=pgv.AGraph()
A.add_edge(1,2)
A.add_edge(2,3)
A.add_edge(1,3)
print(A.string()) # print to screen
print("Wrote simple.dot")
A.write('simple.dot') # write to simple.dot
B=pgv.AGraph('simple.dot') # create a new graph from file
B.layout() # layout with default (neato)
B.draw('simple.png') # draw png
print("Wrote simple.png")
</span>
</pre><span style="font-size:18px;"></span><pre name="code" class="html"><span style="font-size:18px;">tar -zxvf xxxxxxx.tar.gz
python setup.py install</span>
<span style="font-size:18px;">python setup.py install </span>
sudo apt-get install python-dev
参考资料:[1]
pygraphviz python库:https://github.com/pygraphviz/pygraphviz
官网:http://www.graphviz.org/
博客: http://www.cnblogs.com/rocketfan/archive/2009/09/09/1563628.htmlhttp://blog.sina.com.cn/s/blog_6a6c136d0101eacr.html
http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/
sudo pip install pygraphviz --install-option="--include-path=/usr/include/graphviz" --install-option="--library-path=/usr/lib/graphviz/"
*************************************************************************************************************************************************
Graphviz 适合编程快速绘制流程图之类的图形。
而pygraphviz对graphviz进行了封装,提供python程序调用接口。网上有很多对graphiviz进行python封装的程序如pydot等等,个人觉得pygraphviz比较好用,有好的文档和示例程序。https://networkx.lanl.gov/trac/browser/pygraphviz/
在ubuntu下面安装 graphviz
sudo apt-get install graphviz, graphviz-dev
注意graphiviz-dev是pygraphviz所依赖的必须安装。
安装pygraphviz
注意不要sudo apt-get了,因为这样安装的不是最新版本,程序运行会有问题。
到这个地址下载最新的pygraphviz-0.99.1.tar.gz (md5)
http://pypi.python.org/pypi/pygraphviz/
解压缩,然后 sudo python2.6 setup.py install即可。
下面给个例子,如何利用graphiviz 的布局绘制下面的图形呢:
2 // dot s.dot -Tpng -o s.png -Gsplines=line
3 digraph G {
4 // a -> c;
5 a -> b;
6 b -> c;
7 subgraph x{
8 rank = same;
9 b -> d;
10 }
11 subgraph y{
12 // rank = same;
13 d -> e;
14 }
15 subgraph z{
16 rank = same;
17 c -> e;
18 }
19
20 }
21
这里解释下,默认的图布局是自上到下的,TD,当然你可以改成自左向右布局,
digraph G {
rankdir=LR;
.....
}
但是一个时刻只能有一种布局方式,例如上图是采用从上到下的布局方式,为了使得边b->d能够水平,需要采用
subgraph 的方法添加子图,同时说明rank=same.
dot s.dot -Tpng -o s.png -Gsplines=line 中-Gsplines=line 表示强迫边是直线.
http://www.graphviz.org/mywiki/FaqBalanceTree
2 a -> b0
3 xb [label = "" ,width = . 1 ,style = invis]
4 a -> xb [style = invis]
5 a -> b1
6 {rank = same b0 -> xb -> b1 [style = invis]}
7 b0 -> c0
8 xc [label = "" ,width = . 1 ,style = invis]
9 b0 -> xc [style = invis]
10 b0 -> c1
11 {rank = same c0 -> xc -> c1 [style = invis]}
12 }
下面给出利用pygrahviz进行二叉树的绘制
首先给出最简单的绘制,然后是按照上面提到的利用invis属性,构造不可见的顶点和边强迫产生较合适的位置。
a
|
b0—t--b1 原理如昨图所示,对照上面的图示a到b0,a到b1是实边,t为不可见点,a到t,b0到t,t到b1都是不可见边,
这样强迫布局的时候对于横坐标,a尽量在b0,b1的中间。
1.不采用不可见点,边的二叉树绘制效果
1 #printTreeOld.py
3
4 A = pgv.AGraph(directed = True,strict = True)
5 A.add_edge( 1 , 2 )
6 A.add_edge( 1 , 3 )
7 A.add_edge( 2 , 4 )
8 A.add_edge( 2 , 5 )
9 A.add_edge( 5 , 6 )
10 A.add_edge( 5 , 7 )
11 A.add_edge( 3 , 8 )
12 A.add_edge( 3 , 9 )
13 A.add_edge( 8 , 10 )
14 A.add_edge( 8 , 11 )
15 A.graph_attr[ ' epsilon ' ] = ' 0.001 '
16 print A. string () # print dot file to standard output
17 A.write( ' fooOld.dot ' )
18 A.layout( ' dot ' ) # layout with dot
19 A.draw( ' fooOld.png ' ) # write to file
2.采用不可见点,边,绘制二叉树的效果,感觉稍微好一点,更像二叉树了:)
下面的代码仅仅是示例,可以提出子函数简化代码。
2 # strict (no parallel edges)
3 # digraph
4 # with attribute rankdir set to ' LR '
5 A = pgv.AGraph(directed = True,strict = True)
6 A.add_edge( 1 , 2 )
7 A.add_edge( 1 , 3 )
8 A.add_node( ' a ' ,style = ' invis ' )
9 A.add_edge( 1 , ' a ' ,style = ' invis ' )
10 B = A.add_subgraph([ 2 , 3 , ' a ' ],rank = ' same ' )
11 B.add_edge( 2 , ' a ' ,style = ' invis ' )
12 B.add_edge( ' a ' , 3 ,style = ' invis ' )
13
14 A.add_edge( 2 , 4 )
15 A.add_edge( 2 , 5 )
16 A.add_node( ' b ' ,style = ' invis ' )
17 A.add_edge( 2 , ' b ' ,style = ' invis ' )
18 C = A.add_subgraph([ 4 , 5 , ' b ' ],rank = ' same ' )
19 C.add_edge( 4 , ' b ' ,style = ' invis ' )
20 C.add_edge( ' b ' , 5 ,style = ' invis ' )
21
22 A.add_edge( 5 , 6 )
23 A.add_edge( 5 , 7 )
24 A.add_node( ' c ' ,style = ' invis ' )
25 A.add_edge( 5 , ' c ' ,style = ' invis ' )
26 D = A.add_subgraph([ 6 , 7 , ' c ' ],rank = ' same ' )
27 D.add_edge( 6 , ' c ' ,style = ' invis ' )
28 D.add_edge( ' c ' , 7 ,style = ' invis ' )
29
30 A.add_edge( 3 , 8 )
31 A.add_edge( 3 , 9 )
32 A.add_node( ' d ' ,style = ' invis ' )
33 A.add_edge( 3 , ' d ' ,style = ' invis ' )
34 E = A.add_subgraph([ 8 , 9 , ' d ' ],rank = ' same ' )
35 E.add_edge( 8 , ' d ' ,style = ' invis ' )
36 E.add_edge( ' d ' , 9 ,style = ' invis ' )
37
38 A.add_edge( 8 , 10 )
39 A.add_edge( 8 , 11 )
40 A.add_node( ' e ' ,style = ' invis ' )
41 A.add_edge( 8 , ' e ' ,style = ' invis ' )
42 F = A.add_subgraph([ 10 , 11 , ' e ' ],rank = ' same ' )
43 F.add_edge( 10 , ' e ' ,style = ' invis ' )
44 F.add_edge( ' e ' , 11 ,style = ' invis ' )
45
46
47 A.graph_attr[ ' epsilon ' ] = ' 0.001 '
48 print A. string () # print dot file to standard output
49 A.write( ' foo.dot ' )
50 A.layout( ' dot ' ) # layout with dot
51 A.draw( ' foo.png ' ) # write to file
52
参考资料:[1]
pygraphviz python库:https://github.com/pygraphviz/pygraphviz
官网:http://www.graphviz.org/
博客: http://www.cnblogs.com/rocketfan/archive/2009/09/09/1563628.htmlhttp://blog.sina.com.cn/s/blog_6a6c136d0101eacr.html
http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/
参考资料:[1]
pygraphviz python库:https://github.com/pygraphviz/pygraphviz
官网:http://www.graphviz.org/
博客: http://www.cnblogs.com/rocketfan/archive/2009/09/09/1563628.htmlhttp://blog.sina.com.cn/s/blog_6a6c136d0101eacr.html
http://icodeit.org/2012/01/%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E6%B5%81%E7%A8%8B%E5%9B%BE/