首页 > Chemistry, Script > 植化流程图生成脚本

植化流程图生成脚本

[总点击:821次]
2009年9月9日

RT
做植化的同学写报告的时候常常要画分离的流程图,以往大家都是拖啊拖啊的,看起来就恼火,于是就写了这样一个脚本(以后我也要画这种东西嘛),可以将简单的描述语言直接生成流程图,比如,如下的语言就可以生成如下的图:

a#草药样品
b#粗分浸膏
a#$甲醇提取=>b#
c1#正丁醇相
c2#石油醚相
c3#…
c4#水相
b#^$有机溶剂萃取
b#=>c1#
b#=>c2#
b#=>c3#
b#=>c4#
c2#^$继续柱层析分离
c2#=>d1#成分五
c2#=>d2#成分六

生成的流程图

该描述语言语法非常简单:
#前面是 node 的名字,$后面是描述,=> 将两个 node 连接起来,在其中画箭头,可以连续连接 比如 a# => b# => c# 也是可以的,node 后面 => 前面的 $xxx 是线上的注释,如果某一个点要往下分支的话只需用 node#^ 即可,node#^ 后面可以直接加注释,很简单的,看上面那个例子结合图片就可以搞明白了。

运行该脚本需要 python-yapgvb,此脚本受弯弯同学脚本的启发并参考了部分代码(http://python.ubuntu.org.cn/viewtopic.php?f=162&t=180285&sid=e2ae53902848adb1d59c375bf2325043

使用方法:

python liuchengtu.py -o xxx.png deffile

还有很多个性化选项,请参考源码。

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
# Author: xioooli<at>yahoo.com.cn,joolix.com
# Licence GPLv2
# Version 2009.09.09
 
import sys
import yapgvb
import optparse
 
FORMATS = {"png" : yapgvb.formats.png,
        "jpg" : yapgvb.formats.jpg,
        "gif" : yapgvb.formats.gif}
ENGINES = {"dot" : yapgvb.engines.dot,
        "neato" : yapgvb.engines.neato,
        "circo" : yapgvb.engines.circo,
        "twopi" : yapgvb.engines.twopi}
 
if __name__ == '__main__':
#    args = sys.argv
#    if len(args) < 2:
#        print "Usage: python state_machine.py <def file>"
#        sys.exit(0)
 
    parser = optparse.OptionParser()
    parser.add_option("-f", "--format", dest="format",
            help="store the flow chart in FORMAT (png, svg, jpg, gif)",
            metavar="FORMAT", default="png")
    parser.add_option("-o", "--output", dest="output",
            help="save the flow chart to FILE",
            metavar="FILE")
    parser.add_option("-e", "--engine", dest="engine",
            help="the layout ENGINE to use for the flow chart (dot, neato, circo, twopi)",
            metavar="ENGINE", default="dot")
    parser.add_option("-c", "--color", dest="fillcolor",
            help="the fillcolor of the node",
            default="white")
    parser.add_option("--fs", "--font-size", dest="fontsize",
            help="the font size of the text",
            default="12")
    parser.add_option("--nfc", "--node-font-color", dest="nodefontcolor",
            help="the fillcolor of the font in node",
            default="black")
    parser.add_option("--nc", "--node-color", dest="nodecolor",
            help="the color of the node frame",
            default="black")
    parser.add_option("--ec", "--edge-color", dest="edgecolor",
            help="the color of the edge",
            default="black")
    parser.add_option("--efc", "--edge-font-color", dest="edgefontcolor",
            help="the font color of the edge text",
            default="black")
    parser.add_option("-s", "--style", dest="style",
            help="the style of the node",
            default="filled")
    parser.add_option("--ah", "--arrowhead", dest="arrowhead",
            help="the style of the arrowhead",
            default="normal")
    parser.add_option("--as", "--arrowsize", dest="arrowsize",
            help="the size of the arrow",
            default=1)
    parser.add_option("--ns", "--nodesep", dest="nodesep",
            help="the sepration between two nodes",
            default=.5)
    parser.add_option("--sp", "--shape", dest="shape",
            help="the shape of the node",
            default="box")
 
    options, args = parser.parse_args()
    if len(args) < 1:
        parser.print_usage()
        sys.exit(0)
 
    graph = yapgvb.Graph("States")
    graph.rankdir="TB"
    graph.nodesep=options.nodesep
    node_dict = {}
 
    with open(args[0]) as def_file:
        lines = [l.strip() for l in def_file.readlines()]
        for line in lines:
            nodes = line.split("=>")
            prev_node = None
            for node in nodes[::-1]:
                label = node.strip().split("#")
                if not node_dict.has_key(label[0]) and label[0] != "":
                    try:
                        lb=label[1].split("$")[0]
                    except:
                        lb=""
                    node_in_graph = graph.add_node(label=lb,
                            shape=options.shape, fillcolor=options.fillcolor,
                            fontcolor=options.nodefontcolor, fontsize=options.fontsize,
                            style=options.style, color=options.nodecolor, width=0.5)
                    node_dict[label[0]] = node_in_graph
                elif label[0] != "":
                    node_in_graph = node_dict[label[0]]
 
                try:
                       blanknode = node.strip().split("#^")
                       if len(blanknode) >= 2:
                           blanknode = blanknode[0]
                       else:
                           blanknode = ""
                except:
                       blanknode = ""
                if node_dict.has_key(blanknode) and blanknode != "":
                    node_dict[blanknode + "_0"] = node_dict[blanknode]
                    node_in_graph = graph.add_node(label="",     
                            shape="circle", fillcolor=options.edgecolor,
                            color=options.edgecolor, style="filled", height=.05, width=.05)
                    node_dict[blanknode] = node_in_graph
                    edge = node_dict[blanknode + "_0"] - node_dict[blanknode]
                    edge.color=options.edgecolor
                    try:
                        edge.label=" "+node.strip().split("$")[1]
                        edge.fontcolor=options.edgefontcolor
                        edge.fontsize=options.fontsize
                    except:
                        pass
 
                if prev_node:
                    edge = node_in_graph - prev_node
                    edge.color=options.edgecolor
                    edge.arrowhead = options.arrowhead
                    edge.arrowsize = options.arrowsize
                    try:
                        edge.label=" "+node.strip().split("$")[1]
                        edge.fontcolor=options.edgefontcolor
                        edge.fontsize=options.fontsize
                    except:
                        pass
 
                prev_node = node_in_graph
 
    graph.layout(ENGINES[options.engine])
    format = FORMATS[options.format]
    if options.output:
        out_file = options.output
    else:
        out_file = args[0] + "." + format
 
    graph.render(out_file, format)

Chemistry, Script , , ,

  1. roylez
    2009年9月10日20:16 | #1

    我一般是直接写dot文件调用graphviz

  2. xiooli
    2009年9月10日23:20 | #2

    我也发现 graphviz 的 dot 语法很强大哦,不过简单的画个流程图就用这个了,毕竟这个比较方便的处理了分叉的问题,而这个又是植化流程图中必须的,用 graphviz 的话还要自己多画一个节点,倒是也可以用 shell 处理 dot 文件, 当学 python 啦。

本文的评论功能被关闭了.