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[:abc] 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 -> {beta; 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: 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