gviz 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ require_relative "../lib/gviz"
2
+
3
+ simple = Gviz.new
4
+ simple.graph do
5
+ route :main => [:init, :parse, :cleanup, :printf]
6
+ route :init => :make
7
+ route :parse => :execute
8
+ route :execute => [:make, :compare, :printf]
9
+ end
10
+ # simple.save(:a, :svg)
11
+
12
+ enhanced = Gviz.new
13
+ enhanced.graph do
14
+ route :main => [:init, :parse, :cleanup, :printf]
15
+ route :init => :make, :parse => :execute
16
+ route :execute => [:make, :compare, :printf]
17
+ node(:main, :shape => 'box')
18
+ node(:compare, :shape => 'box', :style => 'filled', :color => '.7 .3 1.0')
19
+ node(:make, :label => "make a\nstring")
20
+ edge(:main_printf, :style => 'bold', :label => "100 times", :color => 'red', :weight => 8)
21
+ edge(:main_parse, :weight => 8)
22
+ edge(:main_init, :style => "dotted")
23
+ edge(:execute_compare, :color => 'red')
24
+ end
25
+ # puts enhanced
26
+
27
+ polygonal = Gviz.new
28
+ polygonal.graph do
29
+ route :a => :b, :b => [:c, :d]
30
+ node(:a, :shape => 'polygon', :sides => 5, :peripheries => 3, :style => 'filled', :fillcolor => '#DA70D6')
31
+ node(:c, :shape => 'polygon', :sides => 4, :skew => 0.4, :label => "hellow world", :peripheries => 2, :orientation => 20, :fontname => 'Helvetica', :fontcolor => '#DA70D6')
32
+ node(:d, :shape => 'invtriangle')
33
+ node(:e, :shape => 'polygon', :style => 'setlinewidth(8)', :sides => 4, :distortion => 0.7)
34
+ edge(:b_d, :label => 'path to the world', :decorate => true, :labelfloat => true)
35
+ edge(:a_b, :dir => 'both', :headport => 'se')
36
+ edge(:a_b_1, :dir => 'back')
37
+ global(:rankdir => "TB", :rankseq => 'equally')
38
+ end
39
+ # puts polygonal
40
+
41
+ record = Gviz.new
42
+ record.graph do
43
+ nodes(:shape => 'record')
44
+ route :st1 => [:st2, :st3]
45
+ node(:st1, :label => "<f0> left|<f1> middle|<f2> right")
46
+ node(:st2, :label => "<f0> one|<f1> two")
47
+ node(:st3, :label => "hello\nworld|{b|{c|<here> d|e}|f}|g|h")
48
+ edge("st1:f1_st2:f0")
49
+ edge("st1:f2_st3:here")
50
+ end
51
+ # puts record
52
+
53
+ sub = Gviz.new
54
+ sub.graph do
55
+ subgraph do
56
+ nodes(style:'filled', color:'white')
57
+ global(style:'filled', color:'lightgrey', label:'process #1')
58
+ route(:a0 => :a1, :a1 => :a2, :a2 => :a3)
59
+ end
60
+
61
+ subgraph do
62
+ nodes(style:'filled')
63
+ global(color:'blue', label:'process #2')
64
+ route(:b0 => :b1, :b1 => :b2, :b2 => :b3)
65
+ end
66
+ route :start => [:a0, :b0]
67
+ route :a1 => :b3, :b2 => :a3, :a3 => [:a0, :end], :b3 => :end
68
+ node(:start, shape:'Mdiamond')
69
+ node(:end, shape:'Msquare')
70
+ end
71
+ # sub.save('a', 'png')
Binary file
Binary file
Binary file
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+ require "nokogiri"
3
+ require "open-uri"
4
+
5
+ module Gviz
6
+ class Scraper
7
+ URL = "http://www.graphviz.org/content/"
8
+
9
+ class << self
10
+ def build(path)
11
+ @html ||= get(URL+path)
12
+ parse @html
13
+ end
14
+
15
+ def get(url)
16
+ @html = Nokogiri::HTML(open url)
17
+ rescue OpenURI::HTTPError => e
18
+ STDERR.puts "HTTP Access Error:#{e}"
19
+ exit
20
+ end
21
+
22
+ def parse(html)
23
+ q = []
24
+
25
+ # ## shapes
26
+ # html.css("div.content>table td>a").each do |a|
27
+ # q << a.text
28
+ # end
29
+ # return q.uniq
30
+
31
+ ## arrows
32
+ html.css("table").each_with_index do |tbl, i|
33
+ if i == 5
34
+ tbl.css("td").each do |e|
35
+ txt = e.text.strip.chomp
36
+ q << txt unless txt.empty?
37
+ end
38
+ end
39
+ end
40
+ return q.uniq
41
+
42
+ # ## X11 colors scheme
43
+ # table = html.at("div.content>table").css('td>a').each do |color|
44
+ # txt = color.text.gsub(' ','')
45
+ # q << txt unless txt.match(/^\d+$/)
46
+ # end
47
+ # return q.sort.uniq.group_by { |c| c[/^\D+/]; $& }
48
+ # .flat_map { |k, v| v.sort_by { |c| c[/\d+/].to_i } }
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ if __FILE__ == $0
56
+ # puts Gviz::Scraper.build("node-shapes")
57
+ puts Gviz::Scraper.build("arrow-shapes")
58
+ # puts Gviz::Scraper.build("color-names")
59
+ end
@@ -0,0 +1,108 @@
1
+ digraph G {
2
+ node[style="filled",fillcolor="orchid"];
3
+ edge[arrowhead="none"];
4
+ box[shape="box"];
5
+ polygon[shape="polygon"];
6
+ ellipse[shape="ellipse"];
7
+ oval[shape="oval"];
8
+ circle[shape="circle"];
9
+ point[shape="point"];
10
+ egg[shape="egg"];
11
+ triangle[shape="triangle"];
12
+ plaintext[shape="plaintext"];
13
+ diamond[shape="diamond"];
14
+ trapezium[shape="trapezium"];
15
+ parallelogram[shape="parallelogram"];
16
+ house[shape="house"];
17
+ pentagon[shape="pentagon"];
18
+ hexagon[shape="hexagon"];
19
+ septagon[shape="septagon"];
20
+ octagon[shape="octagon"];
21
+ doublecircle[shape="doublecircle"];
22
+ doubleoctagon[shape="doubleoctagon"];
23
+ tripleoctagon[shape="tripleoctagon"];
24
+ invtriangle[shape="invtriangle"];
25
+ invtrapezium[shape="invtrapezium"];
26
+ invhouse[shape="invhouse"];
27
+ Mdiamond[shape="Mdiamond"];
28
+ Msquare[shape="Msquare"];
29
+ Mcircle[shape="Mcircle"];
30
+ rect[shape="rect"];
31
+ rectangle[shape="rectangle"];
32
+ square[shape="square"];
33
+ none[shape="none"];
34
+ note[shape="note"];
35
+ tab[shape="tab"];
36
+ folder[shape="folder"];
37
+ box3d[shape="box3d"];
38
+ component[shape="component"];
39
+ promoter[shape="promoter"];
40
+ cds[shape="cds"];
41
+ terminator[shape="terminator"];
42
+ utr[shape="utr"];
43
+ primersite[shape="primersite"];
44
+ restrictionsite[shape="restrictionsite"];
45
+ fivepoverhang[shape="fivepoverhang"];
46
+ threepoverhang[shape="threepoverhang"];
47
+ noverhang[shape="noverhang"];
48
+ assembly[shape="assembly"];
49
+ signature[shape="signature"];
50
+ insulator[shape="insulator"];
51
+ ribosite[shape="ribosite"];
52
+ rnastab[shape="rnastab"];
53
+ proteasesite[shape="proteasesite"];
54
+ proteinstab[shape="proteinstab"];
55
+ rpromoter[shape="rpromoter"];
56
+ rarrow[shape="rarrow"];
57
+ larrow[shape="larrow"];
58
+ lpromoter[shape="lpromoter"];
59
+ box -> polygon;
60
+ polygon -> ellipse;
61
+ ellipse -> oval;
62
+ oval -> circle;
63
+ circle -> point[headlabel="point"];
64
+ point -> egg;
65
+ egg -> triangle;
66
+ triangle -> plaintext;
67
+ plaintext -> diamond;
68
+ trapezium -> parallelogram;
69
+ parallelogram -> house;
70
+ house -> pentagon;
71
+ pentagon -> hexagon;
72
+ hexagon -> septagon;
73
+ septagon -> octagon;
74
+ octagon -> doublecircle;
75
+ doublecircle -> doubleoctagon;
76
+ doubleoctagon -> tripleoctagon;
77
+ invtriangle -> invtrapezium;
78
+ invtrapezium -> invhouse;
79
+ invhouse -> Mdiamond;
80
+ Mdiamond -> Msquare;
81
+ Msquare -> Mcircle;
82
+ Mcircle -> rect;
83
+ rect -> rectangle;
84
+ rectangle -> square;
85
+ square -> none;
86
+ note -> tab;
87
+ tab -> folder;
88
+ folder -> box3d;
89
+ box3d -> component;
90
+ component -> promoter;
91
+ promoter -> cds;
92
+ cds -> terminator;
93
+ terminator -> utr;
94
+ utr -> primersite;
95
+ restrictionsite -> fivepoverhang;
96
+ fivepoverhang -> threepoverhang;
97
+ threepoverhang -> noverhang;
98
+ noverhang -> assembly;
99
+ assembly -> signature;
100
+ signature -> insulator;
101
+ insulator -> ribosite;
102
+ ribosite -> rnastab;
103
+ rnastab -> proteasesite;
104
+ proteinstab -> rpromoter;
105
+ rpromoter -> rarrow;
106
+ rarrow -> larrow;
107
+ larrow -> lpromoter;
108
+ }
@@ -0,0 +1,79 @@
1
+ # Shape Varieties
2
+ require_relative "../lib/gviz"
3
+
4
+ shapes = DATA.lines.map(&:chomp).reject { |l| l.empty? }
5
+
6
+ g = Gviz.new
7
+
8
+ g.graph do
9
+ nodes(style:'filled', fillcolor:'orchid')
10
+ edges(arrowhead:'none')
11
+ shapes.each { |shape| node shape.intern, shape: shape }
12
+
13
+ shapes.each_slice(10) do |gr|
14
+ gr.each_cons(2) do |a, b|
15
+ route a.intern => b.intern
16
+ end
17
+ end
18
+ edge(:circle_point, headlabel:'point')
19
+ end
20
+
21
+
22
+ puts g
23
+
24
+ __END__
25
+ box
26
+ polygon
27
+ ellipse
28
+ oval
29
+ circle
30
+ point
31
+ egg
32
+ triangle
33
+ plaintext
34
+ diamond
35
+ trapezium
36
+ parallelogram
37
+ house
38
+ pentagon
39
+ hexagon
40
+ septagon
41
+ octagon
42
+ doublecircle
43
+ doubleoctagon
44
+ tripleoctagon
45
+ invtriangle
46
+ invtrapezium
47
+ invhouse
48
+ Mdiamond
49
+ Msquare
50
+ Mcircle
51
+ rect
52
+ rectangle
53
+ square
54
+ none
55
+ note
56
+ tab
57
+ folder
58
+ box3d
59
+ component
60
+ promoter
61
+ cds
62
+ terminator
63
+ utr
64
+ primersite
65
+ restrictionsite
66
+ fivepoverhang
67
+ threepoverhang
68
+ noverhang
69
+ assembly
70
+ signature
71
+ insulator
72
+ ribosite
73
+ rnastab
74
+ proteasesite
75
+ proteinstab
76
+ rpromoter
77
+ rarrow
78
+ larrow
79
+ lpromoter
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gviz/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "gviz"
8
+ gem.version = Gviz::VERSION
9
+ gem.authors = ["kyoendo"]
10
+ gem.email = ["postagie@gmail.com"]
11
+ gem.description = %q{Ruby's interface of graphviz}
12
+ gem.summary = %q{Ruby's interface of graphviz. It generate a dot file with simple ruby's syntax. }
13
+ gem.homepage = "https://github.com/melborne/Gviz"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,211 @@
1
+ class Gviz
2
+ class Node < Struct.new(:id, :attrs)
3
+ def initialize(id, attrs={})
4
+ raise ArgumentError, "`id` must not include underscores" if id.match(/_/)
5
+ super
6
+ end
7
+
8
+ def to_s
9
+ "#{id}"
10
+ end
11
+ end
12
+
13
+ class Edge < Struct.new(:id, :attrs)
14
+ attr_reader :st, :ed, :seq, :st_port, :ed_port
15
+ def initialize(id, attrs={})
16
+ raise ArgumentError, "`attrs` must a hash" unless attrs.is_a?(Hash)
17
+ id, @st, @ed, @seq, @st_port, @ed_port = parse_id(id)
18
+ super(id, attrs)
19
+ end
20
+
21
+ def to_s
22
+ stp = ":#{st_port}" if st_port
23
+ edp = ":#{ed_port}" if ed_port
24
+ "#{st}#{stp} -> #{ed}#{edp}"
25
+ end
26
+
27
+ def nodes
28
+ [st, ed]
29
+ end
30
+
31
+ private
32
+ def parse_id(id)
33
+ st, ed, seq = "#{id}".split('_')
34
+ st, st_port = st.split(':').map(&:intern)
35
+ ed, ed_port = ed.split(':').map(&:intern)
36
+ id = (seq ? [st, ed, seq] : [st, ed]).join('_').intern
37
+ [id, st, ed, seq.to_i, st_port, ed_port]
38
+ end
39
+ end
40
+
41
+ attr_reader :gnode_attrs, :gedge_attrs, :graph_attrs, :subgraphs, :ranks
42
+ def initialize(name=:G, type=:digraph)
43
+ @name, @type = name, type
44
+ @edges = {}
45
+ @nodes = {}
46
+ @gnode_attrs = {}
47
+ @gedge_attrs = {}
48
+ @graph_attrs = {}
49
+ @subgraphs = []
50
+ @ranks = []
51
+ end
52
+
53
+ def nodeset
54
+ @nodes.values
55
+ end
56
+
57
+ def edgeset
58
+ @edges.values
59
+ end
60
+
61
+ def node(id, attrs={})
62
+ raise ArgumentError, '`id` must a symbol' unless id.is_a?(Symbol)
63
+ Node[id, attrs].tap do |node|
64
+ if exist = @nodes[node.id]
65
+ exist.attrs.update(node.attrs)
66
+ else
67
+ @nodes.update(node.id => node)
68
+ end
69
+ end
70
+ end
71
+
72
+ def edge(id, attrs={})
73
+ unless id.match(/._./)
74
+ raise ArgumentError, '`id` must a symbol in which node names joined with "_"'
75
+ end
76
+ Edge[id.intern, attrs].tap do |edge|
77
+ if exist = @edges[id.intern]
78
+ exist.attrs.update(edge.attrs)
79
+ else
80
+ @edges.update(edge.id => edge)
81
+ create_nodes
82
+ end
83
+ end
84
+ end
85
+
86
+ def nodes(attrs)
87
+ @gnode_attrs.update(attrs)
88
+ end
89
+
90
+ def edges(attrs)
91
+ @gedge_attrs.update(attrs)
92
+ end
93
+
94
+ def global(attrs)
95
+ @graph_attrs.update(attrs)
96
+ end
97
+
98
+ def subgraph(&blk)
99
+ Gviz.new("cluster#{subgraphs.size}", :subgraph).tap do |graph|
100
+ subgraphs << graph
101
+ graph.instance_eval &blk
102
+ end
103
+ end
104
+
105
+ def graph(&blk)
106
+ instance_eval(&blk)
107
+ self
108
+ end
109
+
110
+ def add(*nodes_or_routes)
111
+ nodes_or_routes.each do |unit|
112
+ case unit
113
+ when Hash
114
+ unit.each do |sts, eds|
115
+ Array(sts).product(Array(eds))
116
+ .each { |st, ed| edge([st,ed].join('_').intern) }
117
+ end
118
+ when Symbol
119
+ node(unit)
120
+ else
121
+ raise ArgumentError, 'pass nodes in symbol or edges in hash'
122
+ end
123
+ end
124
+ self
125
+ end
126
+ alias :route :add
127
+
128
+ def rank(type, *nodes)
129
+ types = [:same, :min, :max, :source, :sink]
130
+ unless types.include?(type)
131
+ raise ArgumentError, "type must match any of #{types.join(', ')}"
132
+ end
133
+ @ranks << [type, nodes]
134
+ end
135
+
136
+ def to_s
137
+ result = []
138
+ tabs = " "
139
+ result << "#{@type} #{@name} {"
140
+
141
+ unless graph_attrs.empty?
142
+ result << tabs + build_attrs(graph_attrs, false).join(";\n#{tabs}") + ";"
143
+ end
144
+
145
+ unless gnode_attrs.empty?
146
+ result << tabs + "node#{build_attrs(gnode_attrs)};"
147
+ end
148
+
149
+ unless gedge_attrs.empty?
150
+ result << tabs + "edge#{build_attrs(gedge_attrs)};"
151
+ end
152
+
153
+ @nodes.values.each do |node|
154
+ result << tabs + "#{node.id}#{build_attrs(node.attrs)};"
155
+ end
156
+
157
+ @edges.values.each do |edge|
158
+ result << tabs + "#{edge}#{build_attrs(edge.attrs)};"
159
+ end
160
+
161
+ subgraphs.each do |graph|
162
+ graph.to_s.lines do |line|
163
+ result << tabs + line.chomp
164
+ end
165
+ end
166
+
167
+ @ranks.each do |type, nodes|
168
+ result << tabs + "{ rank=#{type}; #{nodes.join('; ')}; }"
169
+ end
170
+
171
+ result << "}\n"
172
+ result.join("\n")
173
+ end
174
+
175
+ def save(path, type=nil)
176
+ File.open("#{path}.dot", "w") { |f| f.puts self }
177
+ system "dot -T#{type} #{path}.dot -o #{path}.#{type}" if type
178
+ end
179
+
180
+ private
181
+ def create_nodes
182
+ # only create unregistered nodes
183
+ ids = @edges.values.flat_map(&:nodes).uniq - @nodes.keys
184
+ ids.each { |id| node(id) }
185
+ @nodes
186
+ end
187
+
188
+ def build_attrs(attrs, join=true)
189
+ return nil if attrs.empty?
190
+ arr = attrs.map { |k, v| %(#{k}="#{v}").gsub("\n", "\\n") }
191
+ join ? '[' + arr.join(',') + ']' : arr
192
+ end
193
+ end
194
+
195
+ if __FILE__ == $0
196
+ g = Gviz.new
197
+ g.graph do
198
+ add(:main => [:printf, :parse, :init, :cleanup])
199
+ add(:parse => :execute, :init => :make)
200
+ add(:execute => [:printf, :compare, :make])
201
+ node(:main, :shape => 'box')
202
+ node(:make, :label => "make a\nstring")
203
+ node(:compare, :shape => 'box', :style => 'filled', :color => ".7 .3 1.0")
204
+ edge(:main_parse, :weight => 8)
205
+ edge(:main_init, :style => 'dotted')
206
+ edge(:main_printf, :style => 'bold', :label => "100 times", :color => 'red')
207
+ edge(:execute_compare, :color => 'red')
208
+ end
209
+ puts g
210
+ end
211
+