JAL-2629 hmmbuild runs on the alignment by default
[jalview.git] / src / jalview / hmmer / HMMBuildThread.java
1 package jalview.hmmer;
2
3
4 import jalview.bin.Cache;
5 import jalview.datamodel.AlignmentI;
6 import jalview.datamodel.HiddenMarkovModel;
7 import jalview.datamodel.Sequence;
8 import jalview.datamodel.SequenceGroup;
9 import jalview.datamodel.SequenceI;
10 import jalview.gui.AlignFrame;
11 import jalview.gui.AlignViewport;
12 import jalview.gui.JvOptionPane;
13 import jalview.gui.Preferences;
14 import jalview.io.DataSourceType;
15 import jalview.io.FileParse;
16 import jalview.io.HMMFile;
17 import jalview.util.MessageManager;
18 import jalview.ws.params.ArgumentI;
19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.IOException;
23 import java.util.ArrayList;
24 import java.util.List;
25
26 import javax.swing.JOptionPane;
27
28 public class HMMBuildThread implements Runnable
29 {
30   HMMERCommands cmds = new HMMERCommands();
31   AlignFrame af;
32
33   AlignViewport viewport;
34
35   AlignmentI alignment;
36   SequenceGroup group;
37   List<ArgumentI> params;
38
39
40   boolean forGroup = false;
41
42   File hmmTemp = null;
43
44   File stoTemp = null;
45
46   long barID;
47   
48   /**
49    * This is used for validation purposes. Do not use!
50    * 
51    * @param viewport
52    */
53   public HMMBuildThread(AlignmentI alignment)
54   {
55     this.alignment = alignment;
56     forGroup = false;
57   }
58
59   public HMMBuildThread(AlignFrame af, List<ArgumentI> args)
60   {
61     this.af = af;
62     viewport = af.getViewport();
63     params = args;
64   }
65
66   /**
67    * Builds a HMM from an alignment, then imports and adds it to the alignment.
68    */
69   @Override
70   public void run()
71   {
72     barID = System.currentTimeMillis();
73     if (af != null)
74     {
75     af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
76             barID);
77     }
78     cmds.HMMERFOLDER = Cache.getProperty(Preferences.HMMER_PATH);
79
80     List<SequenceGroup> groups = new ArrayList<>();
81     if (params != null)
82     {
83       for (ArgumentI arg : params)
84       {
85         String name = arg.getName();
86         if (MessageManager.getString("label.hmmbuild_for").equals(name))
87         {
88           String value = arg.getValue();
89           if ("Alignment".equals(value))
90           {
91             alignment = viewport.getAlignment();
92             break;
93           }
94           else if ("All groups and alignment".equals(value))
95           {
96             alignment = viewport.getAlignment();
97             groups.addAll(viewport.getAlignment().getGroups());
98             break;
99           }
100           else if ("All groups".equals(value))
101           {
102             alignment = null;
103             groups = viewport.getAlignment().getGroups();
104             break;
105           }
106           else if ("Selected group".equals(value))
107           {
108             alignment = null;
109             groups.add(viewport.getSelectionGroup());
110             break;
111           }
112         }
113         else if (MessageManager.getString("label.use_reference")
114                 .equals(name))
115         {
116           if (!af.getViewport().hasReferenceAnnotation())
117           {
118             if (af != null)
119             {
120               af.setProgressBar(
121                       MessageManager.getString("status.running_hmmbuild"),
122                       barID);
123             }
124             JvOptionPane.showInternalMessageDialog(af, MessageManager
125                     .getString("warn.no_reference_annotation"));
126             return;
127           }
128         }
129       }
130     }
131     else
132     {
133       alignment = viewport.getAlignment();
134     }
135
136     if (alignment != null)
137     {
138       forGroup = false;
139       runHMMBuild();
140     }
141
142     if (alignment == null)
143     {
144       alignment = viewport.getAlignment();
145     }
146
147     if (groups != null && groups.size() > 0)
148     {
149       for (SequenceGroup grp : groups)
150       {
151         group = grp;
152         forGroup = true;
153         runHMMBuild();
154       }
155     }
156
157
158     if (af != null)
159     {
160       af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
161               barID);
162     }
163   }
164
165   private void runHMMBuild()
166   {
167     if (alignment == null && group == null)
168       {
169         JOptionPane.showMessageDialog(af,
170               MessageManager.getString("warn.no_sequence_data"));
171       }
172       try
173       {
174         hmmTemp = File.createTempFile("hmm", ".hmm");
175         hmmTemp.deleteOnExit();
176         stoTemp = File.createTempFile("output", ".sto");
177         stoTemp.deleteOnExit();
178       } catch (IOException e1)
179       {
180         e1.printStackTrace();
181       }
182
183     try
184     {
185       try
186       {
187         SequenceI[] array;
188         List<SequenceI> seqs = null;
189         if (forGroup)
190         {
191           seqs = group.getHMMConsensusSequences(true);
192           if (seqs.size() > 0)
193           {
194             return;
195           }
196           array = group.getSelectionAsNewSequences(alignment);
197         }
198         else
199         {
200           seqs = alignment.getHMMConsensusSequences(true);
201           if (!alignment.isAligned())
202           {
203             alignment.padGaps();
204           }
205           array = alignment.getSequencesArray();
206         }
207
208           cmds.setHmmSeqs(seqs);
209
210         if (array.length < 1)
211           {
212           if (af != null)
213           {
214             JOptionPane.showMessageDialog(af,
215                     MessageManager.getString("warn.no_sequence_data"));
216           }
217           return;
218           }
219           SequenceI[] newArr = new SequenceI[array.length];
220           int index = 0;
221           for (SequenceI seq : array)
222           {
223             newArr[index] = new Sequence(seq);
224             index++;
225           }
226
227           cmds.uniquifySequences(newArr);
228           cmds.exportData(newArr, stoTemp, null, null);
229           jalview.analysis.SeqsetUtils.deuniquify(cmds.hash, array);
230
231       } catch (FileNotFoundException e)
232       {
233         // TODO Auto-generated catch block
234         e.printStackTrace();
235
236       }
237       try
238       {
239           boolean ran = runCommand();
240           if (!ran)
241           {
242             return;
243           }
244       } catch (IOException | InterruptedException e)
245       {
246         // TODO Auto-generated catch block
247         e.printStackTrace();
248       }
249       try
250       {
251
252         importData();
253       } catch (IOException | InterruptedException e)
254       {
255         // TODO Auto-generated catch block
256         e.printStackTrace();
257       }
258       } catch (Exception e)
259       {
260         e.printStackTrace();
261     }
262   }
263
264   
265
266   /**
267    * Executes the hmmbuild command in the command line.
268    * 
269    * @return
270    * @throws IOException
271    * @throws InterruptedException
272    */
273   private boolean runCommand() throws IOException, InterruptedException
274   {
275     File file = new File(cmds.HMMERFOLDER + "/hmmbuild");
276     if (!file.canExecute())
277     {
278       file = new File(cmds.HMMERFOLDER + "/hmmbuild.exe");
279       {
280         if (!file.canExecute())
281         {
282           if (af != null)
283           {
284             JvOptionPane.showInternalMessageDialog(af,
285                     MessageManager.getString("warn.hmmbuild_failed"));
286           }
287           return false;
288         }
289       }
290     }
291     String command = cmds.HMMERFOLDER + cmds.HMMBUILD + cmds.SPACE;
292     String name = null;
293
294     if (params != null)
295     {
296       for (ArgumentI arg : params)
297       {
298         String argName = arg.getName();
299         switch (argName)
300         {
301         case "HMM Name":
302           name = arg.getValue();
303           name = name.trim();
304           break;
305         case "Use Reference Annotation":
306           command += "--hand ";
307           break;
308
309         }
310
311       }
312     }
313
314
315
316     if (name == null || "".equals(name))
317     {
318       if (forGroup)
319       {
320         name = group.getName();
321       }
322       else
323       {
324         if (af != null)
325         {
326           name = af.getTitle();
327         }
328         if (name == null || "".equals(name))
329         {
330           name = "Alignment";
331         }
332       }
333     }
334
335     command += "-n " + name.replace(' ', '_') + cmds.SPACE;
336     if (!alignment.isNucleotide())
337     {
338       command += cmds.FORCEAMINO; // TODO check for rna
339     }
340     else
341     {
342       command += cmds.FORCEDNA;
343     }
344
345     command += hmmTemp.getAbsolutePath()
346             + cmds.SPACE + stoTemp.getAbsolutePath() + cmds.SPACE;
347     return cmds.runCommand(command);
348   }
349   
350   /**
351    * Imports the .hmm file produced by hmmbuild.
352    * 
353    * @throws IOException
354    * @throws InterruptedException
355    */
356   private void importData() throws IOException, InterruptedException
357   {
358       HMMFile file = new HMMFile(new FileParse(hmmTemp.getAbsolutePath(),
359               DataSourceType.FILE));
360     SequenceI[] seqs = file.getSeqsAsArray();
361     SequenceI seq = seqs[0];
362     seq.createDatasetSequence();
363     HiddenMarkovModel hmm = file.getHMM();
364     if (group != null)
365     {
366       seq.insertCharAt(0, group.getStartRes(), '-');
367       seq.insertCharAt(group.getEndRes() + 1,
368               alignment.getWidth() - group.getEndRes(), '-');
369       seq.updateHMMMapping();
370       SequenceI topSeq = group.getSequencesInOrder(alignment)[0];
371       int topIndex = alignment.findIndex(topSeq);
372       alignment.insertSequenceAt(topIndex, seq);
373       group.setSeqrep(seq);
374       group.addSequence(seq, false);
375     }
376     else
377     {
378       alignment.insertSequenceAt(0, seq);
379     }
380
381     viewport.alignmentChanged(viewport.getAlignPanel());
382     viewport.getAlignPanel().adjustAnnotationHeight();
383     viewport.updateSequenceIdColours();
384
385     if (viewport.getAlignPanel().alignFrame.getSelectedHMM() == null)
386     {
387       viewport.getAlignPanel().alignFrame.setSelectedHMMSequence(seq);
388     }
389     hmmTemp.delete();
390     stoTemp.delete();
391   }
392   
393   /**
394    * Runs hmmbuild, and waits for the results to be imported before continuing
395    */
396   public void hmmbuildWaitTillComplete()
397   {
398     Thread loader = new Thread(this);
399     loader.start();
400
401     while (loader.isAlive())
402     {
403       try
404       {
405         Thread.sleep(500);
406       } catch (Exception ex)
407       {
408       }
409     }
410   }
411 }