class Bio::PAML::Common

Description

Bio::PAML::Common is a basic wrapper class for PAML programs. The class provides methods for generating the necessary configuration file, and running a program.

Constants

DEFAULT_PARAMETERS

Default parameters. Should be redefined in subclass.

DEFAULT_PARAMETERS_ORDER

Preferred order of parameters.

DEFAULT_PROGRAM

Default program. Should be redifined in subclass.

Attributes

command[R]

the last executed command (Array of String)

data_stdout[R]

the last output to the stdout (String)

exit_status[R]

the last exit status of the program

output[R]

the last result of the program (String)

parameters[RW]

Parameters described in the control file. (Hash) Each key of the hash must be a Symbol object, and each value must be a String object or nil.

report[R]

Report object created from the last result

supplemental_outputs[R]

contents of supplemental output files (Hash). Each key is a file name and value is content of the file.

Public Class Methods

new(program = nil, params = {}) click to toggle source

Creates a wrapper instance, which will run using the specified binary location or the command in the PATH. If program is specified as nil, DEFAULT_PROGRAM is used. Default parameters are automatically loaded and merged with the specified parameters.


Arguments:

  • (optional) program: path to the program, or command name (String)

  • (optional) params: parameters (Hash)

# File lib/bio/appl/paml/common.rb, line 73
def initialize(program = nil, params = {})
  @program = program || self.class::DEFAULT_PROGRAM
  set_default_parameters
  self.parameters.update(params)
end

Public Instance Methods

dump_parameters() click to toggle source

Shows parameters (content of control file) as a string. The string can be used for control file.


Returns

string representation of the parameters (String)

# File lib/bio/appl/paml/common.rb, line 270
def dump_parameters
  keyorder = DEFAULT_PARAMETERS_ORDER
  keys = parameters.keys
  str = ''
  keys.sort do |x, y|
    (keyorder.index(x) || (keyorder.size + keys.index(x))) <=>
      (keyorder.index(y) || (keyorder.size + keys.index(y)))
  end.each do |key|
    value = parameters[key]
    # Note: spaces are required in both side of the "=".
    str.concat "#{key.to_s} = #{value.to_s}\n" if value
  end
  str
end
load_parameters(str) click to toggle source

Loads parameters from the specified string. Note that all previous parameters are erased. Returns the parameters as a hash.


Arguments:

  • (required) str: contents of a PAML control file (String)

Returns

parameters (Hash)

# File lib/bio/appl/paml/common.rb, line 248
def load_parameters(str)
  hash = {}
  str.each_line do |line|
    param, value = parse_parameter(line)
    hash[param] = value if param
  end
  self.parameters = hash
end
query(alignment, tree = nil) click to toggle source

Runs the program on the internal parameters with the specified sequence alignment and tree.

Note that parameters and parameters are always modified, and parameters is modified when tree is specified.

To prevent overwrite of existing files by PAML, this method automatically creates a temporary directory and the program is run inside the directory. After the end of the program, the temporary directory is automatically removed.


Arguments:

Returns

Report object

# File lib/bio/appl/paml/common.rb, line 117
def query(alignment, tree = nil)
  astr = alignment.output(:phylipnon)
  if tree then
    tstr = [ sprintf("%3d %2d\n", tree.leaves.size, 1), "\n",
             tree.output(:newick,
                         { :indent => false,
                           :bootstrap_style => :disabled,
                           :branch_length_style => :disabled })
           ].join('')
  else
    tstr = nil
  end
  str = _query_by_string(astr, tstr)
  @report = self.class::Report.new(str)
  @report
end
query_by_string(alignment = nil, tree = nil) click to toggle source

Runs the program on the internal parameters with the specified sequence alignment data string and tree data string.

Note that parameters is always modified, and parameters and parameters are modified when alignment and tree are specified respectively.

It raises RuntimeError if seqfile is not specified in the argument or in the parameter.

For other information, see the document of query method.


Arguments:

  • (optional) alignment: String

  • (optional) tree: String or nil

Returns

contents of output file (String)

# File lib/bio/appl/paml/common.rb, line 151
def query_by_string(alignment = nil, tree = nil)
  _query_by_string(alignment, tree)
end
run(control_file) click to toggle source

Runs the program on the parameters in the passed control file. No parameters checks are performed. All internal parameters are ignored and are kept untouched. The output and report attributes are cleared in this method.

Warning about PAML's behavior: PAML writes supplemental output files in the current directory with fixed file names which can not be changed with parameters or command-line options, for example, rates, rst, and rub. This behavior may ovarwrite existing files, especially previous supplemental results.


Arguments:

  • (optional) control_file: file name of control file (String)

Returns

messages printed to the standard output (String)

# File lib/bio/appl/paml/common.rb, line 95
def run(control_file)
  exec_local([ control_file ])
end
set_default_parameters() click to toggle source

Loads system-wide default parameters. Note that all previous parameters are erased. Returns the parameters as a hash.


Returns

parameters (Hash)

# File lib/bio/appl/paml/common.rb, line 262
def set_default_parameters
  self.parameters = self.class::DEFAULT_PARAMETERS.merge(Hash.new)
end

Private Instance Methods

_query_by_string(alignment = nil, tree = nil) click to toggle source

(private) implementation of #query_by_string().

# File lib/bio/appl/paml/common.rb, line 156
def _query_by_string(alignment = nil, tree = nil)
  @parameters ||= {}
  Bio::Command.mktmpdir('paml') do |path|
    #$stderr.puts path.inspect
    filenames = []
    begin
      # preparing outfile
      outfile = Tempfile.new('out', path)
      outfile.close(false)
      outfn = File.basename(outfile.path)
      self.parameters[:outfile] = outfn
      filenames.push outfn
      # preparing seqfile
      if alignment then
        seqfile = Tempfile.new('seq', path)
        seqfile.print alignment
        seqfile.close(false)
        seqfn = File.basename(seqfile.path)
        self.parameters[:seqfile] = seqfn
        filenames.push seqfn
      end
      # preparing treefile
      if tree then
        treefile = Tempfile.new('tree', path)
        treefile.print tree
        treefile.close(false)
        treefn = File.basename(treefile.path)
        self.parameters[:treefile] = treefn
        filenames.push treefn
      end
      # preparing control file
      ctlfile = Tempfile.new('control', path)
      ctlfile.print self.dump_parameters
      ctlfile.close(false)
      ctlfn = File.basename(ctlfile.path)
      filenames.push ctlfn
      # check parameters
      if errors = check_parameters then
        msg = errors.collect { |e| "error in parameter #{e[0]}: #{e[1]}" }
        raise RuntimeError, msg.join("; ")
      end
      # exec command
      stdout = exec_local([ ctlfn ], { :chdir => path })
      # get main output
      outfile.open
      @output = outfile.read
      # get supplemental result files
      @supplemental_outputs = {}
      (Dir.entries(path) - filenames).each do |name|
        next unless /\A\w/ =~ name
        fn = File.join(path, name)
        if File.file?(fn) then
          @supplemental_outputs[name] = File.read(fn)
        end
      end
    ensure
      outfile.close(true) if outfile
      seqfile.close(true) if seqfile
      treefile.close(true) if treefile
      ctlfile.close(true) if ctlfile
    end
  end
  @output
end
check_parameters() click to toggle source

(private) Checks parameters. Returns nil if no errors found. Otherwise, returns an Array containing [ parameter, message ] pairs.


Arguments:

Returns

nil or Array

# File lib/bio/appl/paml/common.rb, line 337
def check_parameters
  errors = []
  param = self.parameters
  if !param[:seqfile] or param[:seqfile].empty? then
    errors.push([ :seqfile, 'seqfile not specified' ]) 
  end
  errors.empty? ? nil : errors
end
exec_local(arguments, options = {}) click to toggle source

(private) Runs the program on the parameters in the passed control file. No parameter check are executed.


Arguments:

  • (optional) control_file: file name of control file (String)

Returns

messages printed to the standard output (String)

# File lib/bio/appl/paml/common.rb, line 321
def exec_local(arguments, options = {})
  reset
  cmd = [ @program, *arguments ]
  @command = cmd
  stdout = Bio::Command.query_command(cmd, nil, options)
  @exit_status = $?
  @data_stdout = stdout
  stdout
end
parse_parameter(line) click to toggle source

(private) parses a parameter in a line


Arguments:

  • (required) line: single line string (String)

Returns

parameter name (Symbol or nil), value (String or nil)

# File lib/bio/appl/paml/common.rb, line 302
def parse_parameter(line)
  # remove comment
  line = line.sub(/\*.*/, '')
  # Note: spaces are required in both side of the "=".
  param, value = line.strip.split(/\s+=\s+/, 2)
  if !param or param.empty? then
    param = nil
  else
    param = param.to_sym
  end
  return param, value
end
reset() click to toggle source

(private) clear attributes except program and parameters

# File lib/bio/appl/paml/common.rb, line 288
def reset
  @command = nil
  @output = nil
  @report = nil
  @exit_status = nil
  @data_stdout = nil
  @supplemental_outputs = nil
end