ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/owl/trunk/tinker/TinkerRunner.java
Revision: 322
Committed: Tue Sep 18 13:59:33 2007 UTC (17 years, 1 month ago) by duarte
Original Path: trunk/proteinstructure/TinkerRunner.java
File size: 14502 byte(s)
Log Message:
Initial commit of TinkerRunner and exception class to go with it TinkerError
Line User Rev File contents
1 duarte 322 package proteinstructure;
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     * @param xyzFile
156     * @param outPath Directory where output files will be written
157     * @param outBasename Base name of the output files
158     * @param n Number of models that we want distgeom to produce
159     * @throws TinkerError If an error seen in tinker's output
160     * @throws IOException
161     */
162     public void runDistgeom(File xyzFile, String outPath, String outBasename, int n) throws TinkerError, IOException {
163     boolean tinkerError = false; // to store the exit state of the tinker program
164     if (!new File(outPath).exists()) {
165     throw new FileNotFoundException("Specified directory "+outPath+" does not exist");
166     }
167     if (!xyzFile.exists()){
168     throw new FileNotFoundException("Specified xyz file "+xyzFile.getAbsolutePath()+" does not exist");
169     }
170     String basename = xyzFile.getName();
171     basename = basename.substring(0, basename.lastIndexOf("."));
172     File keyFile = new File(xyzFile.getParent(),basename+".key");
173     if (! keyFile.exists()) {
174     throw new FileNotFoundException("Key file "+keyFile.getAbsolutePath()+" not present in input directory "+xyzFile.getParent());
175     }
176     // getting names of tinker output files
177     File[] tinkerout = new File[n+1];
178     for (int i=1;i<=n;i++) {
179     String ext = new Formatter().format("%03d", i).toString();
180     tinkerout[i] = getTinkerOutputFileName(xyzFile, ext);
181     }
182     // initialising arrays were we store captured output data
183     numUpperBoundViol = new int[n+1];
184     numLowerBoundViol = new int[n+1];
185     maxUpperBoundViol = new double[n+1];
186     maxLowerBoundViol = new double[n+1];
187     rmsBoundViol = new double[n+1];
188     numUpperViol = new int[n+1];
189     numLowerViol = new int[n+1];
190     maxUpperViol = new double[n+1];
191     maxLowerViol = new double[n+1];
192     rmsRestViol = new double[n+1];
193     // running distgeom program
194     Process dgeomProc = Runtime.getRuntime().exec(distgeomProg+" "+xyzFile.getAbsolutePath()+" "+n+" "+DGEOM_PARAMS);
195     // logging and capturing output
196     BufferedReader dgeomOutput = new BufferedReader(new InputStreamReader(dgeomProc.getInputStream()));
197     String line;
198     int i=1;
199     while((line = dgeomOutput.readLine()) != null) {
200     log.println(line);
201     if (line.startsWith(TINKER_ERROR_STR)) {
202     tinkerError = true;
203     }
204     Pattern p = Pattern.compile("^ Num Upper Bound Violations :\\s+(\\d+)");
205     Matcher m = p.matcher(line);
206     if (m.find()) {
207     numUpperBoundViol[i]=Integer.parseInt(m.group(1));
208     }
209     p = Pattern.compile("^ Num Lower Bound Violations :\\s+(\\d+)");
210     m = p.matcher(line);
211     if (m.find()) {
212     numLowerBoundViol[i]=Integer.parseInt(m.group(1));
213     }
214     p = Pattern.compile("^ Max Upper Bound Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
215     m = p.matcher(line);
216     if (m.find()) {
217     maxUpperBoundViol[i]=Double.parseDouble(m.group(1));
218     }
219     p = Pattern.compile("^ Max Lower Bound Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
220     m = p.matcher(line);
221     if (m.find()) {
222     maxLowerBoundViol[i]=Double.parseDouble(m.group(1));
223     }
224     p = Pattern.compile("^ RMS Deviation from Bounds :\\s+(\\d+\\.\\d\\d\\d\\d)");
225     m = p.matcher(line);
226     if (m.find()) {
227     rmsBoundViol[i]=Double.parseDouble(m.group(1));
228     }
229     p = Pattern.compile("^ Num Upper Restraint Violations :\\s+(\\d+)");
230     m = p.matcher(line);
231     if (m.find()) {
232     numUpperViol[i]=Integer.parseInt(m.group(1));
233     }
234     p = Pattern.compile("^ Num Lower Restraint Violations :\\s+(\\d+)");
235     m = p.matcher(line);
236     if (m.find()) {
237     numLowerViol[i]=Integer.parseInt(m.group(1));
238     }
239     p = Pattern.compile("^ Max Upper Restraint Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
240     m = p.matcher(line);
241     if (m.find()) {
242     maxUpperViol[i]=Double.parseDouble(m.group(1));
243     }
244     p = Pattern.compile("^ Max Lower Restraint Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
245     m = p.matcher(line);
246     if (m.find()) {
247     maxLowerViol[i]=Double.parseDouble(m.group(1));
248     }
249     p = Pattern.compile("^ RMS Restraint Dist Violation :\\s+(\\d+\\.\\d\\d\\d\\d)");
250     m = p.matcher(line);
251     if (m.find()) {
252     rmsRestViol[i]=Double.parseDouble(m.group(1));
253     i++;
254     }
255     }
256     //renaming files to our chosen outBasename+ext
257     for (i=1;i<=n;i++) {
258     String ext = new Formatter().format("%03d", i).toString();
259     tinkerout[i].renameTo(new File(outPath,outBasename+"."+ext));
260     }
261     // throwing exception if error string was caught in output
262     if (tinkerError) {
263     log.close();
264     throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
265     }
266    
267     }
268    
269     /**
270     * Runs tinker's xyzpdb program to convert a given xyzFile (needing also a seqFile) to a pdbFile
271     * @param xyzFile
272     * @param seqFile
273     * @param pdbFile
274     * @throws IOException
275     * @throws TinkerError If an error seen in tinker's output
276     */
277     public void runXyzpdb(File xyzFile, File seqFile, File pdbFile) throws IOException, TinkerError {
278     boolean tinkerError = false; // to store the exit state of the tinker program
279     if (!xyzFile.exists()){
280     throw new FileNotFoundException("Specified xyz file "+xyzFile.getAbsolutePath()+" does not exist");
281     }
282     if (!seqFile.exists()){
283     throw new FileNotFoundException("Specified seq file "+seqFile.getAbsolutePath()+" does not exist");
284     }
285    
286     String basename = xyzFile.getName();
287     basename = basename.substring(0, basename.lastIndexOf("."));
288     File tmpSeqFile = new File(seqFile.getParent(),basename+".seq");
289    
290     // 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)
291     if (!tmpSeqFile.equals(seqFile)) {
292     FileChannel srcChannel = new FileInputStream(seqFile).getChannel();
293     FileChannel dstChannel = new FileOutputStream(tmpSeqFile).getChannel();
294     dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
295     srcChannel.close();
296     dstChannel.close();
297     // if we copied then that means tmpSeqFile is different from seqFile and thus we want to delete the tmp file on exit
298     tmpSeqFile.deleteOnExit();
299     }
300    
301     File tinkerpdbout = getTinkerOutputFileName(xyzFile, "pdb");
302    
303     // running tinker's xyzpdb
304     // beware: it takes as a silent input the seq file seqFile (or tmpSeqFile if the input seqFile didn't have the right name)
305     Process xyzpdbProc = Runtime.getRuntime().exec(xyzpdbProg+" "+xyzFile.getAbsolutePath()+" "+forceFieldFileName);
306    
307     // logging output
308     BufferedReader xyzpdbOutput = new BufferedReader(new InputStreamReader(xyzpdbProc.getInputStream()));
309     String line;
310     while((line = xyzpdbOutput.readLine()) != null) {
311     log.println(line);
312     if (line.startsWith(TINKER_ERROR_STR)) {
313     tinkerError = true;
314     }
315     }
316    
317     tinkerpdbout.renameTo(pdbFile);
318    
319     if (tinkerError) {
320     log.close();
321     throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
322     }
323     }
324    
325     /**
326     * Runs tinker's pdbxyz program to convert a pdbFile to a xyzFile
327     * @param pdbFile
328     * @param xyzFile
329     * @throws IOException
330     * @throws TinkerError If an error seen in tinker's output
331     */
332     public void runPdbxyz(File pdbFile, File xyzFile) throws IOException, TinkerError{
333     boolean tinkerError = false; // to store the exit state of the tinker program
334     if (!pdbFile.exists()){
335     throw new FileNotFoundException("Specified pdb file "+pdbFile.getAbsolutePath()+" does not exist");
336     }
337     File tinkerxyzout = getTinkerOutputFileName(pdbFile, "xyz");
338     // running tinker's pdbxyz
339     Process pdbxyzProc = Runtime.getRuntime().exec(pdbxyzProg+" "+pdbFile.getAbsolutePath()+" "+forceFieldFileName);
340    
341     // logging output
342     BufferedReader pdbxyzOutput = new BufferedReader(new InputStreamReader(pdbxyzProc.getInputStream()));
343     String line;
344     while((line = pdbxyzOutput.readLine()) != null) {
345     log.println(line);
346     if (line.startsWith(TINKER_ERROR_STR)) {
347     tinkerError = true;
348     }
349     }
350     tinkerxyzout.renameTo(xyzFile);
351     if (tinkerError) {
352     log.close();
353     throw new TinkerError("Tinker error, revise log file "+logFile.getAbsolutePath());
354     }
355     }
356    
357     /**
358     * Closes log stream, must be called after no other tinker program will be run with this TinkerRunner object
359     * (otherwise log is not flushed to file)
360     */
361     public void closeLog() {
362     log.close();
363     }
364    
365     public double[] getMaxLowerBoundViol() {
366     return maxLowerBoundViol;
367     }
368    
369     public double[] getMaxLowerViol() {
370     return maxLowerViol;
371     }
372    
373     public double[] getMaxUpperBoundViol() {
374     return maxUpperBoundViol;
375     }
376    
377     public double[] getMaxUpperViol() {
378     return maxUpperViol;
379     }
380    
381     public int[] getNumLowerBoundViol() {
382     return numLowerBoundViol;
383     }
384    
385     public int[] getNumLowerViol() {
386     return numLowerViol;
387     }
388    
389     public int[] getNumUpperBoundViol() {
390     return numUpperBoundViol;
391     }
392    
393     public int[] getNumUpperViol() {
394     return numUpperViol;
395     }
396    
397     public double[] getRmsBoundViol() {
398     return rmsBoundViol;
399     }
400    
401     public double[] getRmsRestViol() {
402     return rmsRestViol;
403     }
404     }