植化流程图生成脚本
[总点击:821次]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) |
我一般是直接写dot文件调用graphviz
我也发现 graphviz 的 dot 语法很强大哦,不过简单的画个流程图就用这个了,毕竟这个比较方便的处理了分叉的问题,而这个又是植化流程图中必须的,用 graphviz 的话还要自己多画一个节点,倒是也可以用 shell 处理 dot 文件, 当学 python 啦。