JAL-2629 Javadoc updates
[jalview.git] / src / jalview / hmmer / HmmerCommand.java
1 package jalview.hmmer;
2
3 import jalview.analysis.SeqsetUtils;
4 import jalview.bin.Cache;
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.AnnotatedCollectionI;
9 import jalview.datamodel.Annotation;
10 import jalview.datamodel.HiddenMarkovModel;
11 import jalview.datamodel.SequenceI;
12 import jalview.gui.AlignFrame;
13 import jalview.gui.JvOptionPane;
14 import jalview.gui.Preferences;
15 import jalview.io.HMMFile;
16 import jalview.io.StockholmFile;
17 import jalview.util.MessageManager;
18 import jalview.ws.params.ArgumentI;
19
20 import java.io.BufferedReader;
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStreamReader;
24 import java.io.PrintWriter;
25 import java.util.Hashtable;
26 import java.util.List;
27
28 /**
29  * Base class for hmmbuild, hmmalign and hmmsearch
30  * 
31  * @author TZVanaalten
32  *
33  */
34 public abstract class HmmerCommand implements Runnable
35 {
36   public static final String HMMBUILD = "hmmbuild";
37
38   protected final AlignFrame af;
39
40   protected final AlignmentI alignment;
41
42   protected final List<ArgumentI> params;
43
44   /**
45    * Constructor
46    * 
47    * @param alignFrame
48    * @param args
49    */
50   public HmmerCommand(AlignFrame alignFrame, List<ArgumentI> args)
51   {
52     af = alignFrame;
53     alignment = af.getViewport().getAlignment();
54     params = args;
55   }
56
57   /**
58    * Answers true if preference HMMER_PATH is set, and its value is the path to
59    * a directory that contains an executable <code>hmmbuild</code> or
60    * <code>hmmbuild.exe</code>, else false
61    * 
62    * @return
63    */
64   public static boolean isHmmerAvailable()
65   {
66     File exec = getExecutable(HMMBUILD, Cache.getProperty(Preferences.HMMER_PATH));
67     return exec != null;
68   }
69
70   /**
71    * Uniquifies the sequences when exporting and stores their details in a
72    * hashtable
73    * 
74    * @param seqs
75    */
76   protected Hashtable stashSequences(SequenceI[] seqs)
77   {
78     return SeqsetUtils.uniquify(seqs, true);
79   }
80
81   /**
82    * Restores the sequence data lost by uniquifying
83    * 
84    * @param hashtable
85    * @param seqs
86    */
87   protected void recoverSequences(Hashtable hashtable, SequenceI[] seqs)
88   {
89     SeqsetUtils.deuniquify(hashtable, seqs);
90   }
91
92   /**
93    * Runs a command as a separate process and waits for it to complete. Answers
94    * true if the process return status is zero, else false.
95    * 
96    * @param command
97    *          the executable command and any arguments to it
98    * @throws IOException
99    */
100   public boolean runCommand(List<String> command)
101           throws IOException
102   {
103     try
104     {
105       ProcessBuilder pb = new ProcessBuilder(command);
106       pb.redirectErrorStream(true); // merge syserr to sysout
107       final Process p = pb.start();
108       new Thread(new Runnable()
109       {
110         @Override
111         public void run()
112         {
113           BufferedReader input = new BufferedReader(
114                   new InputStreamReader(p.getInputStream()));
115           try
116           {
117             String line = input.readLine();
118             while (line != null)
119             {
120               System.out.println(line);
121               line = input.readLine();
122             }
123           } catch (IOException e)
124           {
125             e.printStackTrace();
126           }
127         }
128       }).start();
129
130       p.waitFor();
131       return p.exitValue() == 0; // 0 is success, by convention
132     } catch (Exception e)
133     {
134       e.printStackTrace();
135       return false;
136     }
137   }
138
139   /**
140    * Exports an alignment, and reference (RF) annotation if present, to the
141    * specified file, in Stockholm format
142    * 
143    * @param seqs
144    * @param toFile
145    * @param annotated
146    * @throws IOException
147    */
148   public void exportStockholm(SequenceI[] seqs, File toFile,
149           AnnotatedCollectionI annotated) throws IOException
150   {
151     if (seqs == null)
152     {
153       return;
154     }
155     AlignmentI newAl = new Alignment(seqs);
156     if (!newAl.isAligned())
157     {
158       newAl.padGaps();
159     }
160
161     if (toFile != null && annotated != null)
162     {
163       AlignmentAnnotation[] annots = annotated.getAlignmentAnnotation();
164       if (annots != null)
165       {
166         for (AlignmentAnnotation annot : annots)
167         {
168           if (annot.label.contains("Reference") || "RF".equals(annot.label))
169           {
170             AlignmentAnnotation newRF;
171             if (annot.annotations.length > newAl.getWidth())
172             {
173               Annotation[] rfAnnots = new Annotation[newAl.getWidth()];
174               System.arraycopy(annot.annotations, 0, rfAnnots, 0,
175                       rfAnnots.length);
176               newRF = new AlignmentAnnotation("RF", "Reference Positions",
177                       rfAnnots);
178             }
179             else
180             {
181               newRF = new AlignmentAnnotation(annot);
182             }
183             newAl.addAnnotation(newRF);
184           }
185         }
186       }
187     }
188
189     StockholmFile file = new StockholmFile(newAl);
190     String output = file.print(seqs, false);
191     PrintWriter writer = new PrintWriter(toFile);
192     writer.println(output);
193     writer.close();
194   }
195
196   /**
197    * Answers the full path to the given hmmer executable, or null if file cannot
198    * be found or is not executable
199    * 
200    * @param cmd
201    *          command short name e.g. hmmalign
202    * @return
203    */
204   protected String getCommandPath(String cmd)
205   {
206     String binariesFolder = Cache.getProperty(Preferences.HMMER_PATH);
207     File file = getExecutable(cmd, binariesFolder);
208     if (file == null && af != null)
209     {
210         JvOptionPane.showInternalMessageDialog(af,
211                 MessageManager.getString("warn.hmm_command_failed"));
212     }
213
214     return file == null ? null : file.getAbsolutePath();
215   }
216
217   /**
218    * Answers the executable file for the given hmmer command, or null if not
219    * found or not executable. The path to the executable is the command name
220    * prefixed by the hmmer binaries folder path, optionally with .exe appended.
221    * 
222    * @param cmd
223    *          hmmer command short name, for example hmmbuild
224    * @param binaryPath
225    *          parent folder containing hmmer executables
226    * @return
227    */
228   public static File getExecutable(String cmd, String binaryPath)
229   {
230     File file = new File(binaryPath, cmd);
231     if (!file.canExecute())
232     {
233       file = new File(binaryPath, cmd + ".exe");
234       {
235         if (!file.canExecute())
236         {
237           file = null;
238         }
239       }
240     }
241     return file;
242   }
243
244   /**
245    * A convenience method to create a temporary file that is deleted on exit of
246    * the JVM
247    * 
248    * @param prefix
249    * @param suffix
250    * @return
251    * @throws IOException
252    */
253   protected File createTempFile(String prefix, String suffix)
254           throws IOException
255   {
256     File f = File.createTempFile(prefix, suffix);
257     f.deleteOnExit();
258     return f;
259
260   }
261
262   /**
263    * Exports an HMM to the specified file
264    * 
265    * @param hmm
266    * @param hmmFile
267    * @throws IOException
268    */
269   public void exportHmm(HiddenMarkovModel hmm, File hmmFile)
270           throws IOException
271   {
272     if (hmm != null)
273     {
274       HMMFile file = new HMMFile(hmm);
275       PrintWriter writer = new PrintWriter(hmmFile);
276       writer.print(file.print());
277       writer.close();
278     }
279   }
280 }