Class: GraphvizR

Inherits:
Object
  • Object
show all
Defined in:
lib/graphviz_r.rb

Overview

GraphvizR is graphviz adapter for Ruby, and it can:

  • generate a graphviz dot file, and
  • generate an image file directly.

A sample code to generate dot file is:

gvr = GraphvizR.new 'sample'
gvr.graph [:label => 'example', :size => '1.5, 2.5'] 
gvr.alpha >> gvr.beta
gvr.beta >> gvr.delta
gvr.delta >> gvr.gamma
gvr.to_dot

The code generates a dot file look like:

digraph sample {
graph [label = "example", size = "1.5, 2.5"];
beta [shape = box];
alpha -> beta;
beta -> delta;
delta -> gamma;
}

Node

A node can be created by method calling or array accessing to GraphvizR instance. In short, both gvr.abc and gvr generate the abc node in dot file.

Edge

An edge is generated by >> of - method calling to a node; the former generate a directed graph while the latter a undirected one. For example, gvr = GraphvizR.new 'sample' gvr.alpha >> gvr.beta generates digraph sample { alpla -> beta } while gvr = GraphvizR.new 'sample' gvr.alpha - gvr.beta generates graph sample { alpla -- beta }

Grouping Nodes

When one node is the root of some nodes, you can aggregate the children by using an array. For example, gvr = GraphvizR.new 'sample' gvr.alpha >> [gvr.beta, gvr.gamma, gvr.delta] generates digraph sample { alpha -> gamma; delta; }

Consective Edges

You can write:

gvr = GraphvizR.new 'sample'
gvr.alpha >> gvr.beta >> gvr.gamma >> gvr.delta

instead of doing:

gvr = GraphvizR.new 'sample'
gvr.alpha >> gvr.beta
gvr.beta >> gvr.gamma
gvr.gamma >> gvr.delta

Graph Attributes

Attributes are specified by Hash in []. Thus, to set the fillcolor of a node abc, one would use gvr = GraphvizR.new 'sample' gvr.abc [:fillcolor => :red]

Similarly, to set the arrowhead style of an edge abc -> def, one would use (gvr.abc >> gvr.def) [:arrowhead => :diamond]

As you can expect, to set graph attributes, one would use gvr.graph [:label => 'example', :size => '1.5, 2.5']

Record

To set a record label on a node, you can use ordinary [] method. gvr.node1 [:label => "<p_left> left|<p_center>center|<p_right> right"]

To access a record in a node, you can use method calling whose argumemts is the name of a record. gvr.node1(:p_left) >> gvr.node2

Accordingly, a full example looks like:

gvr = GraphvizR.new 'sample'
gvr.node [:shape => :record]
gvr.node1 [:label => "<p_left> left|<p_center>center|<p_right> right"]
gvr.node2
gvr.node1(:p_left) >> gvr.node2
gvr.node2 >> gvr.node1(:p_center)
(gvr.node2 >> gvr.node1(:p_right)) [:label => 'record']
gvr.to_dot

Rank

Ranks of nodes can be set as the same value for other nodes. gvr.rank :same, [gvr.a, gvr.b, gvr.c] means node a, b, and c has same rank value and generages:

{rank = same; a; b; c;};

Clusters

Cluster is a way to construct hierarchical graph in graphviz. GraphvizR allows you to use clusters by means of method calling with a block which has one argument. For example, gvr = GraphvizR.new 'sample' gvr.cluster0 do |c0| c0.graph [:color => :blue, :label => 'area 0', :style => :bold] c0.a >> c0.b c0.a >> c0.c end gvr.cluster1 do |c1| c1.graph [:fillcolor => '#cc9966', :label => 'area 1', :style => :filled] c1.d >> c1.e c1.d >> c1.f end (gvr.a >> gvr.f) [:lhead => :cluster1, :ltail => :cluster0] gvr.b >> gvr.d (gvr.c >> gvr.d) [:ltail => :cluster0] (gvr.c >> gvr.f) [:lhead => :cluster1] gvr.to_dot generates digraph sample { subgraph cluster0 { graph [color = blue, label ="area 0", style = bold]; a -> b; a -> c; } subgraph cluster1 { graph [fillcolor = "#cc9966", label = "area 1", style = filled]; d -> e; d -> f; } a -> f [lhead = cluster1, ltail = cluster0]; b -> d; c -> d [ltail = cluster0]; c -> f [lhead = cluster1];

Defined Under Namespace

Classes: Edge, Node, NodeGroup

Constant Summary collapse

VERSION =
'0.5.1'
INDENT_UNIT =
'  '

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, parent = nil, indent = 0) ⇒ GraphvizR

This initialzes a GraphvizR instance.

name

the name of the graph

parent

a parent graph is given when this graph is a subgraph.

indent

indent level when this instance is converted to rdot.



153
154
155
156
157
158
159
160
# File 'lib/graphviz_r.rb', line 153

def initialize(name, parent=nil, indent=0)
  @name = name
  @parent = parent
  @graph_type = 'digraph'
  @indent = indent
  @directed = true
  @statements = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object

redirect to [] method.



233
234
235
# File 'lib/graphviz_r.rb', line 233

def method_missing(name, *args, &block) #:nodoc:
  self.send(:"[]", name, *args, &block)
end

Instance Attribute Details

#graph_typeObject (readonly)

Returns the value of attribute graph_type.



147
148
149
# File 'lib/graphviz_r.rb', line 147

def graph_type
  @graph_type
end

#statementsObject (readonly)

Returns the value of attribute statements.



147
148
149
# File 'lib/graphviz_r.rb', line 147

def statements
  @statements
end

Instance Method Details

#[](name, *args, &block) ⇒ Object

if block is not given, this generates a node. if block given, generates a subgraph.



164
165
166
167
168
169
170
171
172
173
174
# File 'lib/graphviz_r.rb', line 164

def [](name, *args, &block)
  if block
    subgraph = self.class.new name, self, @indent + 1
    block.call subgraph
    @statements << subgraph
  else
    node = Node.new name, args, self
    @statements << node
    node
  end
end

#data(format = 'png') ⇒ Object

If format is 'dot', a dot string is generated. Otherwise, this generates image file in the given format, such as 'png', 'gif', 'jpg', and so on. To know correctly, please see the specification of graphviz: http://www.graphviz.org/doc/info/output.html



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/graphviz_r.rb', line 195

def data(format='png')
  format = format.to_s
  if format == 'dot'
    to_dot
  else
    begin
      gv = IO.popen "dot -q -T#{format || 'png'}", "w+"
      gv.puts to_dot
      gv.close_write
      gv.read
    ensure
      gv.close
    end
  end
end

#output(filename = nil, format = 'png') ⇒ Object

store image data created from this instance to given file.



212
213
214
215
216
217
# File 'lib/graphviz_r.rb', line 212

def output(filename=nil, format='png')
  img = data(format)
  File.open(filename || "#{@name}.#{format || 'png'}", "w+") do |file|
    file.write img
  end
end

#rank(same, nodes = []) ⇒ Object

set all nodes as same level



183
184
185
186
187
188
189
190
# File 'lib/graphviz_r.rb', line 183

def rank(same, nodes=[])
  group = NodeGroup.new nodes, :rank => same
  nodes.size.times do
    @statements.pop
  end
  @statements << group
  group
end

#to_dot(indent = @indent) ⇒ Object

convert this instance to dot



220
221
222
223
224
225
226
227
228
229
230
# File 'lib/graphviz_r.rb', line 220

def to_dot(indent=@indent)
  to_subgraph if @parent
  dot = INDENT_UNIT * indent
  dot += "#{@graph_type} #{@name} {\n"
  @statements.each do |statement|
    dot += statement.to_dot(indent + 1)
  end
  dot += INDENT_UNIT * indent
  dot += "}\n"
  dot
end