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

Source Code for Module Bio.Phylo.PAML.baseml

  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  import os 
  7  import os.path 
  8  from ._paml import Paml, _relpath 
  9  from . import _parse_baseml 
 10   
 11   
12 -class BasemlError(EnvironmentError):
13 """BASEML has failed. Run with verbose = True to view BASEML's error 14 message"""
15 16
17 -class Baseml(Paml):
18 """This class implements an interface to BASEML, part of the PAML package.""" 19
20 - def __init__(self, alignment = None, tree = None, working_dir = None, 21 out_file = None):
22 """Initialize the Baseml instance. 23 24 The user may optionally pass in strings specifying the locations 25 of the input alignment and tree files, the working directory and 26 the final output file. 27 """ 28 Paml.__init__(self, alignment, working_dir, out_file) 29 if tree is not None: 30 if not os.path.exists(tree): 31 raise IOError("The specified tree file does not exist.") 32 self.tree = tree 33 self.ctl_file = "baseml.ctl" 34 self._options = {"noisy": None, 35 "verbose": None, 36 "runmode": None, 37 "model": None, 38 "model_options": None, 39 "Mgene": None, 40 "ndata": None, 41 "clock": None, 42 "fix_kappa": None, 43 "kappa": None, 44 "fix_alpha": None, 45 "alpha": None, 46 "Malpha": None, 47 "ncatG": None, 48 "fix_rho": None, 49 "rho": None, 50 "nparK": None, 51 "nhomo": None, 52 "getSE": None, 53 "RateAncestor": None, 54 "Small_Diff": None, 55 "cleandata": None, 56 "icode": None, 57 "fix_blength": None, 58 "method": None}
59
60 - def write_ctl_file(self):
61 """Dynamically build a BASEML control file from the options. 62 63 The control file is written to the location specified by the 64 ctl_file property of the baseml class. 65 """ 66 # Make sure all paths are relative to the working directory 67 self._set_rel_paths() 68 if True: # Dummy statement to preserve indentation for diff 69 with open(self.ctl_file, 'w') as ctl_handle: 70 ctl_handle.write("seqfile = %s\n" % self._rel_alignment) 71 ctl_handle.write("outfile = %s\n" % self._rel_out_file) 72 ctl_handle.write("treefile = %s\n" % self._rel_tree) 73 for option in self._options.items(): 74 if option[1] is None: 75 # If an option has a value of None, there's no need 76 # to write it in the control file; it's normally just 77 # commented out. 78 continue 79 if option[0] == "model_options": 80 continue 81 # If "model" is 9 or 10, it may be followed in the cotnrol 82 # file by further options such as 83 # [1 (TC CT AG GA)] 84 # or 85 # [5 (AC CA) (AG GA) (AT TA) (CG GC) (CT TC)] 86 # which are to be stored in "model_options" as a string. 87 if option[0] == "model" and option[1] in [9, 10]: 88 if self._options["model_options"] is not None: 89 ctl_handle.write("model = %s %s" % (option[1], 90 self._options["model_options"])) 91 continue 92 ctl_handle.write("%s = %s\n" % (option[0], option[1]))
93
94 - def read_ctl_file(self, ctl_file):
95 """Parse a control file and load the options into the Baseml instance. 96 """ 97 temp_options = {} 98 if not os.path.isfile(ctl_file): 99 raise IOError("File not found: %r" % ctl_file) 100 else: 101 with open(ctl_file) as ctl_handle: 102 for line in ctl_handle: 103 line = line.strip() 104 uncommented = line.split("*", 1)[0] 105 if uncommented != "": 106 if "=" not in uncommented: 107 raise AttributeError( 108 "Malformed line in control file:\n%r" % line) 109 (option, value) = uncommented.split("=") 110 option = option.strip() 111 value = value.strip() 112 if option == "seqfile": 113 self.alignment = value 114 elif option == "treefile": 115 self.tree = value 116 elif option == "outfile": 117 self.out_file = value 118 elif option not in self._options: 119 raise KeyError("Invalid option: %s" % option) 120 elif option == "model": 121 if len(value) <= 2 and value.isdigit(): 122 temp_options["model"] = int(value) 123 temp_options["model_options"] = None 124 else: 125 model_num = value.partition(" ")[0] 126 model_opt = value.partition(" ")[2].strip() 127 temp_options["model"] = int(model_num) 128 temp_options["model_options"] = model_opt 129 else: 130 if "." in value or "e-" in value: 131 try: 132 converted_value = float(value) 133 except: 134 converted_value = value 135 else: 136 try: 137 converted_value = int(value) 138 except: 139 converted_value = value 140 temp_options[option] = converted_value 141 for option in self._options: 142 if option in temp_options: 143 self._options[option] = temp_options[option] 144 else: 145 self._options[option] = None
146
147 - def _set_rel_paths(self):
148 """Convert all file/directory locations to paths relative to the current working directory. 149 150 BASEML requires that all paths specified in the control file be 151 relative to the directory from which it is called rather than 152 absolute paths. 153 """ 154 Paml._set_rel_paths(self) 155 if self.tree is not None: 156 self._rel_tree = _relpath(self.tree, self.working_dir)
157
158 - def run(self, ctl_file = None, verbose = False, command = "baseml", 159 parse = True):
160 """Run baseml using the current configuration and then parse the results. 161 162 Return a process signal so the user can determine if 163 the execution was successful (return code 0 is successful, -N 164 indicates a failure). The arguments may be passed as either 165 absolute or relative paths, despite the fact that BASEML 166 requires relative paths. 167 """ 168 if self.tree is None: 169 raise ValueError("Tree file not specified.") 170 if not os.path.exists(self.tree): 171 raise IOError("The specified tree file does not exist.") 172 Paml.run(self, ctl_file, verbose, command) 173 if parse: 174 results = read(self.out_file) 175 else: 176 results = None 177 return results
178 179
180 -def read(results_file):
181 """Parse a BASEML results file.""" 182 results = {} 183 if not os.path.exists(results_file): 184 raise IOError("Results file does not exist.") 185 with open(results_file) as handle: 186 lines = handle.readlines() 187 (results, num_params) = _parse_baseml.parse_basics(lines, results) 188 results = _parse_baseml.parse_parameters(lines, results, num_params) 189 if results.get("version") is None: 190 raise ValueError("Invalid results file") 191 return results
192