Package Bio :: Package Phylo :: Package PAML :: Module _paml
[hide private]
[frames] | no frames]

Source Code for Module Bio.Phylo.PAML._paml

  1  # Copyright (C) 2011 by Brandon Invergo (b.invergo@gmail.com) 
  2  # This code is part of the Biopython distribution and governed by its 
  3  # license. Please see the LICENSE file that should have been included 
  4  # as part of this package. 
  5   
  6  from __future__ import print_function 
  7   
  8  import os 
  9  import subprocess 
 10   
 11   
 12  try: 
 13      from os.path import relpath as _relpath 
 14  except ImportError: 
 15      # New in Python 2.6 
16 - def _relpath(path, start=None):
17 """Return a relative version of a path. 18 19 Implementation by James Gardner in his BareNecessities 20 package, under MIT licence. 21 22 With a fix for Windows where posixpath.sep (and functions like 23 join) use the Unix slash not the Windows slash. 24 """ 25 import posixpath 26 if start is None: 27 start = posixpath.curdir 28 else: 29 start = start.replace(os.path.sep, posixpath.sep) 30 if not path: 31 raise ValueError("no path specified") 32 else: 33 path = path.replace(os.path.sep, posixpath.sep) 34 start_list = posixpath.abspath(start).split(posixpath.sep) 35 path_list = posixpath.abspath(path).split(posixpath.sep) 36 # Work out how much of the filepath is shared by start and path. 37 i = len(posixpath.commonprefix([start_list, path_list])) 38 rel_list = [posixpath.pardir] * (len(start_list) - i) + path_list[i:] 39 if not rel_list: 40 return posixpath.curdir.replace(posixpath.sep, os.path.sep) 41 return posixpath.join(*rel_list).replace(posixpath.sep, os.path.sep)
42 43
44 -class PamlError(EnvironmentError):
45 """paml has failed. Run with verbose = True to view the error 46 message"""
47 48
49 -class Paml(object):
50 """Base class for wrapping PAML commands.""" 51
52 - def __init__(self, alignment=None, working_dir=None, 53 out_file=None):
54 if working_dir is None: 55 self.working_dir = os.getcwd() 56 else: 57 self.working_dir = working_dir 58 if alignment is not None: 59 if not os.path.exists(alignment): 60 raise IOError("The specified alignment file does not exist.") 61 self.alignment = alignment 62 self.out_file = out_file 63 self._options = {} # will be set in subclasses
64
65 - def write_ctl_file(self):
66 pass
67
68 - def read_ctl_file(self):
69 pass
70
71 - def print_options(self):
72 """Print out all of the options and their current settings.""" 73 for option in self._options.items(): 74 print("%s = %s" % (option[0], option[1]))
75
76 - def set_options(self, **kwargs):
77 """Set the value of an option. 78 79 This function abstracts the options dict to prevent the user from 80 adding options that do not exist or misspelling options. 81 """ 82 for option, value in kwargs.items(): 83 if option not in self._options: 84 raise KeyError("Invalid option: " + option) 85 else: 86 self._options[option] = value
87
88 - def get_option(self, option):
89 """Return the value of an option.""" 90 if option not in self._options: 91 raise KeyError("Invalid option: " + option) 92 else: 93 return self._options.get(option)
94
95 - def get_all_options(self):
96 """Return the values of all the options.""" 97 return list(self._options.items())
98
99 - def _set_rel_paths(self):
100 """Convert all file/directory locations to paths relative to the current working directory. 101 102 paml requires that all paths specified in the control file be 103 relative to the directory from which it is called rather than 104 absolute paths. 105 """ 106 if self.working_dir is not None: 107 self._rel_working_dir = _relpath(self.working_dir) 108 if self.alignment is not None: 109 self._rel_alignment = _relpath(self.alignment, 110 self.working_dir) 111 if self.out_file is not None: 112 self._rel_out_file = _relpath(self.out_file, self.working_dir)
113
114 - def run(self, ctl_file, verbose, command):
115 """Run a paml program using the current configuration and then parse the results. 116 117 Return a process signal so the user can determine if 118 the execution was successful (return code 0 is successful, -N 119 indicates a failure). The arguments may be passed as either 120 absolute or relative paths, despite the fact that paml 121 requires relative paths. 122 """ 123 if self.alignment is None: 124 raise ValueError("Alignment file not specified.") 125 if not os.path.exists(self.alignment): 126 raise IOError("The specified alignment file does not exist.") 127 if self.out_file is None: 128 raise ValueError("Output file not specified.") 129 if self.working_dir is None: 130 raise ValueError("Working directory not specified.") 131 # Get the current working directory 132 cwd = os.getcwd() 133 # Move to the desired working directory 134 if not os.path.exists(self.working_dir): 135 os.mkdir(self.working_dir) 136 os.chdir(self.working_dir) 137 # If no external control file was specified... 138 if ctl_file is None: 139 # Dynamically build a control file 140 self.write_ctl_file() 141 if verbose: 142 result_code = subprocess.call([command, self.ctl_file]) 143 else: 144 # To suppress output, redirect it to a pipe to nowhere 145 result_code = subprocess.call([command, self.ctl_file], 146 stdout=subprocess.PIPE) 147 else: 148 if not os.path.exists(ctl_file): 149 raise IOError("The specified control file does not exist.") 150 if verbose: 151 result_code = subprocess.call([command, ctl_file]) 152 else: 153 result_code = subprocess.call([command, ctl_file], 154 stdout=subprocess.PIPE) 155 os.chdir(cwd) 156 if result_code > 0: 157 # If the program fails for any reason 158 raise PamlError( 159 "%s has failed (return code %i). Run with verbose = True to view error message" 160 % (command, result_code)) 161 if result_code < 0: 162 # If the paml process is killed by a signal somehow 163 raise EnvironmentError("The %s process was killed (return code %i)." 164 % (command, result_code))
165