1
2
3
4
5
6 import os
7 import subprocess
8
9 try:
10 from os.path import relpath as _relpath
11 except ImportError:
12
14 """Return a relative version of a path.
15
16 Implementation by James Gardner in his BareNecessities
17 package, under MIT licence.
18
19 With a fix for Windows where posixpath.sep (and functions like
20 join) use the Unix slash not the Windows slash.
21 """
22 import posixpath
23 if start is None:
24 start = posixpath.curdir
25 else:
26 start = start.replace(os.path.sep, posixpath.sep)
27 if not path:
28 raise ValueError("no path specified")
29 else:
30 path = path.replace(os.path.sep, posixpath.sep)
31 start_list = posixpath.abspath(start).split(posixpath.sep)
32 path_list = posixpath.abspath(path).split(posixpath.sep)
33
34 i = len(posixpath.commonprefix([start_list, path_list]))
35 rel_list = [posixpath.pardir] * (len(start_list)-i) + path_list[i:]
36 if not rel_list:
37 return posixpath.curdir.replace(posixpath.sep, os.path.sep)
38 return posixpath.join(*rel_list).replace(posixpath.sep, os.path.sep)
39
40
42 """paml has failed. Run with verbose = True to view the error
43 message"""
44
45
47
48 - def __init__(self, alignment = None, working_dir = None,
49 out_file = None):
50 if working_dir is None:
51 self.working_dir = os.getcwd()
52 else:
53 self.working_dir = working_dir
54 if alignment is not None:
55 if not os.path.exists(alignment):
56 raise IOError("The specified alignment file does not exist.")
57 self.alignment = alignment
58 self.out_file = out_file
59
62
65
67 """Print out all of the options and their current settings."""
68 for option in self._options.items():
69 print "%s = %s" % (option[0], option[1])
70
72 """Set the value of an option.
73
74 This function abstracts the options dict to prevent the user from
75 adding options that do not exist or mispelling options.
76 """
77 for option, value in kwargs.items():
78 if not option in self._options:
79 raise KeyError("Invalid option: " + option)
80 else:
81 self._options[option] = value
82
84 """Return the value of an option."""
85 if not option in self._options:
86 raise KeyError("Invalid option: " + option)
87 else:
88 return self._options.get(option)
89
91 """Return the values of all the options."""
92 return self._options.items()
93
95 """Convert all file/directory locations to paths relative to the current working directory.
96
97 paml requires that all paths specified in the control file be
98 relative to the directory from which it is called rather than
99 absolute paths.
100 """
101 if self.working_dir is not None:
102 self._rel_working_dir = _relpath(self.working_dir)
103 if self.alignment is not None:
104 self._rel_alignment = _relpath(self.alignment,
105 self.working_dir)
106 if self.out_file is not None:
107 self._rel_out_file = _relpath(self.out_file, self.working_dir)
108
109 - def run(self, ctl_file, verbose, command):
110 """Run a paml program using the current configuration and then parse the results.
111
112 Return a process signal so the user can determine if
113 the execution was successful (return code 0 is successful, -N
114 indicates a failure). The arguments may be passed as either
115 absolute or relative paths, despite the fact that paml
116 requires relative paths.
117 """
118 if self.alignment is None:
119 raise ValueError("Alignment file not specified.")
120 if not os.path.exists(self.alignment):
121 raise IOError("The specified alignment file does not exist.")
122 if self.out_file is None:
123 raise ValueError("Output file not specified.")
124 if self.working_dir is None:
125 raise ValueError("Working directory not specified.")
126
127 cwd = os.getcwd()
128
129 if not os.path.exists(self.working_dir):
130 os.mkdir(self.working_dir)
131 os.chdir(self.working_dir)
132
133 if ctl_file is None:
134
135 self.write_ctl_file()
136 if verbose:
137 result_code = subprocess.call([command, self.ctl_file])
138 else:
139
140 result_code = subprocess.call([command, self.ctl_file],
141 stdout=subprocess.PIPE)
142 else:
143 if not os.path.exists(ctl_file):
144 raise IOError("The specified control file does not exist.")
145 if verbose:
146 result_code = subprocess.call([command, ctl_file])
147 else:
148 result_code = subprocess.call([command, ctl_file],
149 stdout=subprocess.PIPE)
150 os.chdir(cwd)
151 if result_code > 0:
152
153 raise PamlError(
154 "%s has failed (return code %i). Run with verbose = True to view error message"
155 % (command, result_code))
156 if result_code < 0:
157
158 raise EnvironmentError("The %s process was killed (return code %i)."
159 % (command, result_code))
160