class Graph

Graph models directed graphs and subgraphs and outputs in graphviz’s dot format.

Attributes

edge_attribs[R]

Global attributes for edges in this graph.

edges[R]

The hash of hashes of edges in this graph. Use [] or node to create edges.

graph[RW]

A parent graph, if any. Only used for subgraphs.

graph_attribs[R]

Global attributes for this graph.

name[RW]

The name of the graph. Optional for graphs and subgraphs. Prefix the name of a subgraph with “cluster” for subgraph that is boxed.

node_attribs[R]

Global attributes for nodes in this graph.

nodes[R]

The hash of nodes in this graph. Use [] or node to create nodes.

scheme[RW]

Shortcut method to create a new colorscheme Attribute instance. If passed n, name must match one of the brewer color scheme names and it will generate accessors for each fillcolor as well as push the colorscheme onto the node_attribs.

subgraphs[R]

An array of subgraphs.

Public Class Methods

escape_label(s) click to toggle source
# File lib/graph.rb, line 309
def self.escape_label s
  s = s.to_s.gsub(/\n/, '\n').gsub(/\"/, '\\\"')
  if s[0] == ?< and s[-1] == ?> then
    s
  else
    "\"#{s}\""
  end
end
new(name = nil, graph = nil, &block) click to toggle source

Creates a new graph object. Optional name and parent graph are available. Also takes an optional block for DSL-like use.

# File lib/graph.rb, line 139
def initialize name = nil, graph = nil, &block
  @name = name
  @graph = graph
  graph << self if graph
  @nodes_order = []
  @nodes  = Hash.new { |h,k| @nodes_order << k; h[k] = Node.new self, k }
  @edges_order = []
  @edges  = Hash.new { |h,k|
    h[k] = Hash.new { |h2, k2|
      @edges_order << [k, k2]
      h2[k2] = Edge.new self, self[k], self[k2]
    }
  }
  @graph_attribs = []
  @node_attribs  = []
  @edge_attribs  = []
  @subgraphs     = []

  self.scheme = graph.scheme if graph
  node_attribs << scheme if scheme

  instance_eval(&block) if block
end

Public Instance Methods

<<(subgraph) click to toggle source

Push a subgraph into the current graph. Sets the subgraph’s graph to self.

# File lib/graph.rb, line 166
def << subgraph
  subgraphs << subgraph
  subgraph.graph = self
end
[](name) click to toggle source

Access a node by name

# File lib/graph.rb, line 174
def [] name
  nodes[name]
end
arrowhead(shape) click to toggle source

Shortcut method for creating an arrowhead attribute.

# File lib/graph.rb, line 181
def arrowhead shape
  raise ArgumentError, "Bad arrow shape: #{shape}" unless shape =~ ARROW_RE
  Attribute.new "arrowhead = #{shape}"
end
arrowsize(size) click to toggle source

Shortcut method for creating an arrowsize attribute.

# File lib/graph.rb, line 197
def arrowsize size
  Attribute.new "arrowsize = #{size}"
end
arrowtail(shape) click to toggle source

Shortcut method for creating an arrowtail attribute.

# File lib/graph.rb, line 189
def arrowtail shape
  raise ArgumentError, "Bad arrow shape: #{shape}" unless shape =~ ARROW_RE
  Attribute.new "arrowtail = #{shape}"
end
bgcolor(n) click to toggle source

Shortcut method to create a new fillcolor Attribute instance.

# File lib/graph.rb, line 283
def bgcolor n
  Attribute.new "bgcolor = %p" % [n]
end
boxes() click to toggle source

Shortcut method to set the global node attributes to use boxes.

# File lib/graph.rb, line 204
def boxes
  node_attribs << shape("box")
end
cluster(name, &block) click to toggle source

Shortcut method to create a clustered subgraph in the current graph. Use with the top-level digraph method in block form for a graph DSL.

# File lib/graph.rb, line 397
def cluster name, &block
  subgraph "cluster_#{name}", &block
end
color(color) click to toggle source

Shortcut method to create a new color Attribute instance.

# File lib/graph.rb, line 211
def color color
  Attribute.new "color = #{color}"
end
colorscheme(name, n = nil) click to toggle source

Shortcut method to create and set the graph to use a colorscheme.

# File lib/graph.rb, line 226
def colorscheme name, n = nil
  self.scheme = Attribute.new "colorscheme = %p" % ["#{name}#{n}"]
  max = COLOR_SCHEME_MAX[name.to_sym]

  node_attribs << scheme if max

  scheme
end
compact!() click to toggle source

Shortcut method to rotate and use boxes. Helps compact when there is lots of long text nodes.

# File lib/graph.rb, line 353
def compact!
  rotate
  boxes
end
delete_node(node_name) click to toggle source

Deletes a node from the graph

# File lib/graph.rb, line 403
def delete_node node_name
  nodes.delete node_name
  nodes_order.delete node_name

  edges_order.each do |(a, b)|
    edges[a].delete b if b == node_name
    edges.delete a if a == node_name
    edges.delete a if edges[a].empty?
  end

  edges_order.delete_if { |ary| ary.include? node_name }
end
edge(*names) click to toggle source

Define one or more edges.

edge "a", "b", "c", ...

is equivalent to:

edge "a", "b"
edge "b", "c"
...
# File lib/graph.rb, line 252
def edge(*names)
  last = nil
  names.each_cons(2) do |from, to|
    last = self[from][to]
  end
  last
end
fillcolor(n) click to toggle source

Shortcut method to create a new fillcolor Attribute instance.

# File lib/graph.rb, line 276
def fillcolor n
  Attribute.new "fillcolor = %p" % [n]
end
font(name) click to toggle source

Shortcut method to create a new font Attribute instance. You can pass in both the name and an optional font size.

# File lib/graph.rb, line 291
def font name
  Attribute.new "fontname = %p" % [name]
end
fontcolor(name) click to toggle source

Shortcut method to create a new fontcolor Attribute instance.

# File lib/graph.rb, line 298
def fontcolor name
  Attribute.new "fontcolor = %p" % [name]
end
fontsize(size) click to toggle source

Shortcut method to create a new fontsize Attribute instance.

# File lib/graph.rb, line 305
def fontsize size
  Attribute.new "fontsize = #{size}"
end
invert() click to toggle source

Creates a new Graph whose edges point the other direction.

# File lib/graph.rb, line 263
def invert
  result = self.class.new
  edges.each do |from, h|
    h.each do |to, edge|
      result[to][from]
    end
  end
  result
end
label(name) click to toggle source

Shortcut method to set the graph’s label. Usually used with subgraphs.

# File lib/graph.rb, line 321
def label name
  graph_attribs << "label = #{Graph.escape_label name}"
end
node(name, label = nil) click to toggle source

Access a node by name, supplying an optional label

# File lib/graph.rb, line 328
def node name, label = nil
  n = nodes[name]
  n.label label if label
  n
end
orient(dir = "TB") click to toggle source

Shortcut method to specify the orientation of the graph. Defaults to the graphviz default “TB”.

# File lib/graph.rb, line 338
def orient dir = "TB"
  graph_attribs << "rankdir = #{dir}"
end
rotate(dir = "LR") click to toggle source

Shortcut method to specify the orientation of the graph. Defaults to “LR”.

# File lib/graph.rb, line 345
def rotate dir = "LR"
  orient dir
end
save(path, type = nil, cmd = "dot") click to toggle source

Saves out both a dot file to path and an image for the specified type. Specify type as nil to skip exporting an image. Specify cmd as the command name like “neato” to use a command other than “dot”.

# File lib/graph.rb, line 363
def save path, type = nil, cmd = "dot"
  File.open "#{path}.dot", "w" do |f|
    f.puts self.to_s
  end
  system "#{cmd} -T#{type} #{path}.dot > #{path}.#{type}" if type
end
shape(shape) click to toggle source

Shortcut method to create a new shape Attribute instance.

# File lib/graph.rb, line 373
def shape shape
  Attribute.new "shape = %p" % [shape]
end
style(name) click to toggle source

Shortcut method to create a new style Attribute instance.

# File lib/graph.rb, line 380
def style name
  Attribute.new "style = %p" % [name]
end
subgraph(name = nil, &block) click to toggle source

Shortcut method to create a subgraph in the current graph. Use with the top-level digraph method in block form for a graph DSL.

# File lib/graph.rb, line 388
def subgraph name = nil, &block
  Graph.new name, self, &block
end
to_s() click to toggle source

Outputs a graphviz graph.

# File lib/graph.rb, line 419
def to_s
  result = []

  type = graph ? "subgraph " : "digraph "
  type = "%s%p" % [type, name] if name and !name.empty?
  result << type
  result << "  {"

  graph_attribs.each do |line|
    result << "    #{line};"
  end

  unless node_attribs.empty? then
    result << "    node [ #{node_attribs.join(", ")} ];"
  end

  unless edge_attribs.empty? then
    result << "    edge [ #{edge_attribs.join(", ")} ];"
  end

  subgraphs.each do |line|
    result << "    #{line};"
  end

  nodes_order.each do |name|
    node = nodes[name]
    result << "    #{node};" if graph or node.attributes? or node.orphan?
  end

  edges_order.uniq.each do |(from, to)|
    edge = edges[from][to]
    result << "    #{edge};"
  end

  result << "  }"
  result.join "\n"
end