ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/owl/trunk/tinker/TinkerRunner.java
Revision: 341
Committed: Wed Oct 10 15:14:55 2007 UTC (17 years, 4 months ago) by duarte
File size: 15172 byte(s)
Log Message:
Now capturing exit status 137 (2 instances of tinker running in same machine)
Now outputting progress per model
Line File contents
1 package tinker;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.FileNotFoundException;
7 import java.io.FileOutputStream;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.io.PrintWriter;
11 import java.nio.channels.FileChannel;
12 import java.util.Formatter;
13 import java.util.regex.Matcher;
14 import java.util.regex.Pattern;
15
16 public class TinkerRunner {
17
18 private static final String PROTEIN_PROG = "protein";
19 private static final String DISTGEOM_PROG = "distgeom";
20 private static final String PDBXYZ_PROG = "pdbxyz";
21 private static final String XYZPDB_PROG = "xyzpdb";
22 private static final String CYCLISE_PROTEIN_STR = "N";
23 private static final String DGEOM_PARAMS = "Y N Y Y N N A";
24 private static final String TINKER_ERROR_STR = " TINKER is Unable to Continue";
25
26 private String tinkerBinDir;
27
28 private String forceFieldFileName;
29
30 private String proteinProg;
31 private String distgeomProg;
32 private String pdbxyzProg;
33 private String xyzpdbProg;
34
35 private File logFile;
36 private PrintWriter log;
37
38 // arrays for storing distgeom output data
39 private int[] numUpperBoundViol;
40 private int[] numLowerBoundViol;
41 private double[] maxUpperBoundViol;
42 private double[] maxLowerBoundViol;
43 private double[] rmsBoundViol;
44 private int[] numUpperViol;
45 private int[] numLowerViol;
46 private double[] maxUpperViol;
47 private double[] maxLowerViol;
48 private double[] rmsRestViol;
49
50
51 /**
52 * Constructs a TinkerRunner object by passing initial parameters
53 * @param tinkerBinDir The directory where the tinker executables are
54 * @param forceFieldFileName The force field file
55 * @param logFile File where all tinker output will be logged to
56 * @throws FileNotFoundException If logFile can't be written
57 */
58 public TinkerRunner(String tinkerBinDir, String forceFieldFileName, File logFile) throws FileNotFoundException {
59 this.tinkerBinDir = tinkerBinDir;
60 this.forceFieldFileName = forceFieldFileName;
61 this.proteinProg = new File(this.tinkerBinDir,PROTEIN_PROG).getAbsolutePath();
62 this.distgeomProg = new File(this.tinkerBinDir,DISTGEOM_PROG).getAbsolutePath();
63 this.pdbxyzProg = new File(this.tinkerBinDir,PDBXYZ_PROG).getAbsolutePath();
64 this.xyzpdbProg = new File(this.tinkerBinDir,XYZPDB_PROG).getAbsolutePath();
65
66 this.logFile = logFile;
67 this.log = new PrintWriter(new FileOutputStream(logFile));
68 }
69
70 /**
71 * To get the expected File that a tinker program will output given an input file and an extension for the output files
72 * The directory where the input file is will be scanned to see if it contains files of the form basename.ext, basename.ext_2, basename.ext_3 etc.
73 * @param file
74 * @param ext
75 * @return
76 */
77 private File getTinkerOutputFileName(File file, String ext){
78 String basename = file.getName();
79 basename = basename.substring(0, basename.lastIndexOf("."));
80 String dirname = file.getParent();
81
82 String tinkerOutFileName = basename + "." + ext;
83
84 if (new File(dirname,tinkerOutFileName).exists()) {
85 int i = 2;
86 tinkerOutFileName = basename + "." + ext + "_" + i;
87 while (new File(dirname,tinkerOutFileName).exists()) {
88 i++;
89 tinkerOutFileName = basename + "." + ext + "_" + i;
90 }
91 }
92 return new File(dirname,tinkerOutFileName);
93 }
94
95 /**
96 * Runs tinker's protein program to generate an elongated protein structure given a sequence
97 * @param sequence
98 * @param outPath The directory where output files will be written
99 * @param outBasename The base name for the output files
100 * @throws IOException
101 * @throws TinkerError
102 */
103 public void runProtein(String sequence, String outPath, String outBasename) throws IOException, TinkerError {
104 boolean tinkerError = false; // to store the exit state of the tinker program
105
106 if (!new File(outPath).exists()) {
107 throw new FileNotFoundException("Specified directory "+outPath+" does not exist");
108 }
109 File tinkerxyzout = getTinkerOutputFileName(new File(outPath,outBasename+".xyz"),"xyz");
110 File tinkerintout = getTinkerOutputFileName(new File(outPath,outBasename+".int"),"int");
111 tinkerintout.deleteOnExit();
112 File tinkerseqout = getTinkerOutputFileName(new File(outPath,outBasename+".seq"),"seq");
113
114 // running protein program in outPath dir (so that output files are written to outPath)
115 Process protProc = Runtime.getRuntime().exec(proteinProg, null, new File(outPath));
116 // piping input
117 PrintWriter protInput = new PrintWriter(protProc.getOutputStream());
118 protInput.println(outBasename);
119 protInput.println("Unfolded chain created by tinker's protein program");
120 protInput.println(forceFieldFileName);
121 for (int i=0;i<sequence.length();i++) {
122 // we've got to use 3 letter code for CYS, otherwise tinker takes the default CYX (which means cystein with disulfide bridge)
123 if (sequence.charAt(i)=='C') {
124 protInput.println("CYS");
125 } else {
126 protInput.println(sequence.charAt(i));
127 }
128 }
129 protInput.println();
130 protInput.println(CYCLISE_PROTEIN_STR);
131 protInput.close();
132
133 // logging output
134 BufferedReader protOutput = new BufferedReader(new InputStreamReader(protProc.getInputStream()));
135 String line;
136 while((line = protOutput.readLine()) != null) {
137 log.println(line);
138 if (line.startsWith(TINKER_ERROR_STR)) {
139 tinkerError = true;
140 }
141 }
142
143 tinkerxyzout.renameTo(new File(outPath,outBasename+".xyz"));
144 tinkerseqout.renameTo(new File(outPath,outBasename+".seq"));
145
146 if (tinkerError) {
147 log.close();
148 throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
149 }
150 }
151
152 /**
153 * Runs tinker's distgeom program capturing output with restrain violation statistics into member variable arrays
154 * that can be retrieved using the getters: getMaxLowerBoundViol, getMaxUpperBoundViol, getMaxLowerViol etc...
155 * Two files are needed as input for distgeom: an xyz file and a key file, the latter is not passed but instead implicitely
156 * defined by xyzFile: must be in same directory and must have same basename with extension .key
157 * @param xyzFile
158 * @param outPath Directory where output files will be written
159 * @param outBasename Base name of the output files
160 * @param n Number of models that we want distgeom to produce
161 * @throws TinkerError If an error seen in tinker's output
162 * @throws IOException
163 */
164 public void runDistgeom(File xyzFile, String outPath, String outBasename, int n) throws TinkerError, IOException {
165 boolean tinkerError = false; // to store the exit state of the tinker program
166 if (!new File(outPath).exists()) {
167 throw new FileNotFoundException("Specified directory "+outPath+" does not exist");
168 }
169 if (!xyzFile.exists()){
170 throw new FileNotFoundException("Specified xyz file "+xyzFile.getAbsolutePath()+" does not exist");
171 }
172 String basename = xyzFile.getName();
173 basename = basename.substring(0, basename.lastIndexOf("."));
174 File keyFile = new File(xyzFile.getParent(),basename+".key");
175 if (! keyFile.exists()) {
176 throw new FileNotFoundException("Key file "+keyFile.getAbsolutePath()+" not present in input directory "+xyzFile.getParent());
177 }
178 // getting names of tinker output files
179 File[] tinkerout = new File[n+1];
180 for (int i=1;i<=n;i++) {
181 String ext = new Formatter().format("%03d", i).toString();
182 tinkerout[i] = getTinkerOutputFileName(xyzFile, ext);
183 }
184 // initialising arrays were we store captured output data
185 numUpperBoundViol = new int[n+1];
186 numLowerBoundViol = new int[n+1];
187 maxUpperBoundViol = new double[n+1];
188 maxLowerBoundViol = new double[n+1];
189 rmsBoundViol = new double[n+1];
190 numUpperViol = new int[n+1];
191 numLowerViol = new int[n+1];
192 maxUpperViol = new double[n+1];
193 maxLowerViol = new double[n+1];
194 rmsRestViol = new double[n+1];
195 // running distgeom program
196 Process dgeomProc = Runtime.getRuntime().exec(distgeomProg+" "+xyzFile.getAbsolutePath()+" "+n+" "+DGEOM_PARAMS);
197 // logging and capturing output
198 BufferedReader dgeomOutput = new BufferedReader(new InputStreamReader(dgeomProc.getInputStream()));
199 String line;
200 int i=1;
201 while((line = dgeomOutput.readLine()) != null) {
202 log.println(line);
203 if (line.startsWith(TINKER_ERROR_STR)) {
204 tinkerError = true;
205 }
206 Pattern p = Pattern.compile("^ Num Upper Bound Violations :\\s+(\\d+)");
207 Matcher m = p.matcher(line);
208 if (m.find()) {
209 numUpperBoundViol[i]=Integer.parseInt(m.group(1));
210 }
211 p = Pattern.compile("^ Num Lower Bound Violations :\\s+(\\d+)");
212 m = p.matcher(line);
213 if (m.find()) {
214 numLowerBoundViol[i]=Integer.parseInt(m.group(1));
215 }
216 p = Pattern.compile("^ Max Upper Bound Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
217 m = p.matcher(line);
218 if (m.find()) {
219 maxUpperBoundViol[i]=Double.parseDouble(m.group(1));
220 }
221 p = Pattern.compile("^ Max Lower Bound Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
222 m = p.matcher(line);
223 if (m.find()) {
224 maxLowerBoundViol[i]=Double.parseDouble(m.group(1));
225 }
226 p = Pattern.compile("^ RMS Deviation from Bounds :\\s+(\\d+\\.\\d\\d\\d\\d)");
227 m = p.matcher(line);
228 if (m.find()) {
229 rmsBoundViol[i]=Double.parseDouble(m.group(1));
230 }
231 p = Pattern.compile("^ Num Upper Restraint Violations :\\s+(\\d+)");
232 m = p.matcher(line);
233 if (m.find()) {
234 numUpperViol[i]=Integer.parseInt(m.group(1));
235 }
236 p = Pattern.compile("^ Num Lower Restraint Violations :\\s+(\\d+)");
237 m = p.matcher(line);
238 if (m.find()) {
239 numLowerViol[i]=Integer.parseInt(m.group(1));
240 }
241 p = Pattern.compile("^ Max Upper Restraint Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
242 m = p.matcher(line);
243 if (m.find()) {
244 maxUpperViol[i]=Double.parseDouble(m.group(1));
245 }
246 p = Pattern.compile("^ Max Lower Restraint Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
247 m = p.matcher(line);
248 if (m.find()) {
249 maxLowerViol[i]=Double.parseDouble(m.group(1));
250 }
251 p = Pattern.compile("^ RMS Restraint Dist Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
252 m = p.matcher(line);
253 if (m.find()) {
254 rmsRestViol[i]=Double.parseDouble(m.group(1));
255 System.out.println("Done model "+i+". Violations: "+numUpperViol[i]+" upper, "+numLowerViol[i]+" lower");
256 i++;
257
258 }
259 }
260 //renaming files to our chosen outBasename+ext
261 for (i=1;i<=n;i++) {
262 String ext = new Formatter().format("%03d", i).toString();
263 tinkerout[i].renameTo(new File(outPath,outBasename+"."+ext));
264 }
265 // throwing exception if error string was caught in output
266 if (tinkerError) {
267 log.close();
268 throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
269 }
270 // throwing exception if exit state is 137: happens in Linux when another instance of distgeom is running in same machine, the OS kills it with exit state 137
271 if (dgeomProc.exitValue()==137) {
272 log.close();
273 throw new TinkerError("Distgeom was killed by OS, probably another instance of distgeom is running in this computer");
274 }
275
276 }
277
278 /**
279 * Runs tinker's xyzpdb program to convert a given xyzFile (needing also a seqFile) to a pdbFile
280 * @param xyzFile
281 * @param seqFile
282 * @param pdbFile
283 * @throws IOException
284 * @throws TinkerError If an error seen in tinker's output
285 */
286 public void runXyzpdb(File xyzFile, File seqFile, File pdbFile) throws IOException, TinkerError {
287 boolean tinkerError = false; // to store the exit state of the tinker program
288 if (!xyzFile.exists()){
289 throw new FileNotFoundException("Specified xyz file "+xyzFile.getAbsolutePath()+" does not exist");
290 }
291 if (!seqFile.exists()){
292 throw new FileNotFoundException("Specified seq file "+seqFile.getAbsolutePath()+" does not exist");
293 }
294
295 String basename = xyzFile.getName();
296 basename = basename.substring(0, basename.lastIndexOf("."));
297 File tmpSeqFile = new File(seqFile.getParent(),basename+".seq");
298
299 // if seqFile doesn't follow the naming convention (basename of xyzFile+seq extension) that tinker expects, we copy it to tmpSeqFile (which has right name)
300 if (!tmpSeqFile.equals(seqFile)) {
301 FileChannel srcChannel = new FileInputStream(seqFile).getChannel();
302 FileChannel dstChannel = new FileOutputStream(tmpSeqFile).getChannel();
303 dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
304 srcChannel.close();
305 dstChannel.close();
306 // if we copied then that means tmpSeqFile is different from seqFile and thus we want to delete the tmp file on exit
307 tmpSeqFile.deleteOnExit();
308 }
309
310 File tinkerpdbout = getTinkerOutputFileName(xyzFile, "pdb");
311
312 // running tinker's xyzpdb
313 // beware: it takes as a silent input the seq file seqFile (or tmpSeqFile if the input seqFile didn't have the right name)
314 Process xyzpdbProc = Runtime.getRuntime().exec(xyzpdbProg+" "+xyzFile.getAbsolutePath()+" "+forceFieldFileName);
315
316 // logging output
317 BufferedReader xyzpdbOutput = new BufferedReader(new InputStreamReader(xyzpdbProc.getInputStream()));
318 String line;
319 while((line = xyzpdbOutput.readLine()) != null) {
320 log.println(line);
321 if (line.startsWith(TINKER_ERROR_STR)) {
322 tinkerError = true;
323 }
324 }
325
326 tinkerpdbout.renameTo(pdbFile);
327
328 if (tinkerError) {
329 log.close();
330 throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
331 }
332 }
333
334 /**
335 * Runs tinker's pdbxyz program to convert a pdbFile to a xyzFile
336 * @param pdbFile
337 * @param xyzFile
338 * @throws IOException
339 * @throws TinkerError If an error seen in tinker's output
340 */
341 public void runPdbxyz(File pdbFile, File xyzFile) throws IOException, TinkerError{
342 boolean tinkerError = false; // to store the exit state of the tinker program
343 if (!pdbFile.exists()){
344 throw new FileNotFoundException("Specified pdb file "+pdbFile.getAbsolutePath()+" does not exist");
345 }
346 File tinkerxyzout = getTinkerOutputFileName(pdbFile, "xyz");
347 // running tinker's pdbxyz
348 Process pdbxyzProc = Runtime.getRuntime().exec(pdbxyzProg+" "+pdbFile.getAbsolutePath()+" "+forceFieldFileName);
349
350 // logging output
351 BufferedReader pdbxyzOutput = new BufferedReader(new InputStreamReader(pdbxyzProc.getInputStream()));
352 String line;
353 while((line = pdbxyzOutput.readLine()) != null) {
354 log.println(line);
355 if (line.startsWith(TINKER_ERROR_STR)) {
356 tinkerError = true;
357 }
358 }
359 tinkerxyzout.renameTo(xyzFile);
360 if (tinkerError) {
361 log.close();
362 throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
363 }
364 }
365
366 /**
367 * Closes log stream, must be called after no other tinker program will be run with this TinkerRunner object
368 * (otherwise log is not flushed to file)
369 */
370 public void closeLog() {
371 log.close();
372 }
373
374 public double[] getMaxLowerBoundViol() {
375 return maxLowerBoundViol;
376 }
377
378 public double[] getMaxLowerViol() {
379 return maxLowerViol;
380 }
381
382 public double[] getMaxUpperBoundViol() {
383 return maxUpperBoundViol;
384 }
385
386 public double[] getMaxUpperViol() {
387 return maxUpperViol;
388 }
389
390 public int[] getNumLowerBoundViol() {
391 return numLowerBoundViol;
392 }
393
394 public int[] getNumLowerViol() {
395 return numLowerViol;
396 }
397
398 public int[] getNumUpperBoundViol() {
399 return numUpperBoundViol;
400 }
401
402 public int[] getNumUpperViol() {
403 return numUpperViol;
404 }
405
406 public double[] getRmsBoundViol() {
407 return rmsBoundViol;
408 }
409
410 public double[] getRmsRestViol() {
411 return rmsRestViol;
412 }
413 }