4e0fd0818b6b620654075aa700a922e3fdb8b24d
[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       if (viewport != null && alignment == null)
134       {
135         alignment = viewport.getAlignment();
136       }
137     }
138
139     if (alignment != null)
140     {
141       forGroup = false;
142       runHMMBuild();
143     }
144
145     if (alignment == null)
146     {
147       alignment = viewport.getAlignment();
148     }
149
150     if (groups != null && groups.size() > 0)
151     {
152       for (SequenceGroup grp : groups)
153       {
154         group = grp;
155         forGroup = true;
156         runHMMBuild();
157       }
158     }
159
160
161     if (af != null)
162     {
163       af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
164               barID);
165     }
166   }
167
168   private void runHMMBuild()
169   {
170     if (alignment == null && group == null)
171       {
172         JOptionPane.showMessageDialog(af,
173               MessageManager.getString("warn.no_sequence_data"));
174       }
175       try
176       {
177         hmmTemp = File.createTempFile("hmm", ".hmm");
178         hmmTemp.deleteOnExit();
179         stoTemp = File.createTempFile("output", ".sto");
180         stoTemp.deleteOnExit();
181       } catch (IOException e1)
182       {
183         e1.printStackTrace();
184       }
185
186     try
187     {
188       try
189       {
190         SequenceI[] array;
191         List<SequenceI> seqs = null;
192         if (forGroup)
193         {
194           seqs = group.getHMMConsensusSequences(true);
195           if (seqs.size() > 0)
196           {
197             return;
198           }
199           array = group.getSelectionAsNewSequences(alignment);
200         }
201         else
202         {
203           seqs = alignment.getHMMConsensusSequences(true);
204           if (!alignment.isAligned())
205           {
206             alignment.padGaps();
207           }
208           array = alignment.getSequencesArray();
209         }
210
211           cmds.setHmmSeqs(seqs);
212
213         if (array.length < 1)
214           {
215           if (af != null)
216           {
217             JOptionPane.showMessageDialog(af,
218                     MessageManager.getString("warn.no_sequence_data"));
219           }
220           return;
221           }
222           SequenceI[] newArr = new SequenceI[array.length];
223           int index = 0;
224           for (SequenceI seq : array)
225           {
226             newArr[index] = new Sequence(seq);
227             index++;
228           }
229
230           cmds.uniquifySequences(newArr);
231           cmds.exportData(newArr, stoTemp, null, null);
232           jalview.analysis.SeqsetUtils.deuniquify(cmds.hash, array);
233
234       } catch (FileNotFoundException e)
235       {
236         // TODO Auto-generated catch block
237         e.printStackTrace();
238
239       }
240       try
241       {
242           boolean ran = runCommand();
243           if (!ran)
244           {
245             return;
246           }
247       } catch (IOException | InterruptedException e)
248       {
249         // TODO Auto-generated catch block
250         e.printStackTrace();
251       }
252       try
253       {
254
255         importData();
256       } catch (IOException | InterruptedException e)
257       {
258         // TODO Auto-generated catch block
259         e.printStackTrace();
260       }
261       } catch (Exception e)
262       {
263         e.printStackTrace();
264     }
265   }
266
267   
268
269   /**
270    * Executes the hmmbuild command in the command line.
271    * 
272    * @return
273    * @throws IOException
274    * @throws InterruptedException
275    */
276   private boolean runCommand() throws IOException, InterruptedException
277   {
278     File file = new File(cmds.HMMERFOLDER + "/hmmbuild");
279     if (!file.canExecute())
280     {
281       file = new File(cmds.HMMERFOLDER + "/hmmbuild.exe");
282       {
283         if (!file.canExecute())
284         {
285           if (af != null)
286           {
287             JvOptionPane.showInternalMessageDialog(af,
288                     MessageManager.getString("warn.hmmbuild_failed"));
289           }
290           return false;
291         }
292       }
293     }
294     String command = cmds.HMMERFOLDER + cmds.HMMBUILD + cmds.SPACE;
295     String name = null;
296
297     if (params != null)
298     {
299       for (ArgumentI arg : params)
300       {
301         String argName = arg.getName();
302         switch (argName)
303         {
304         case "HMM Name":
305           name = arg.getValue();
306           name = name.trim();
307           break;
308         case "Use Reference Annotation":
309           command += "--hand ";
310           break;
311
312         }
313
314       }
315     }
316
317
318
319     if (name == null || "".equals(name))
320     {
321       if (forGroup)
322       {
323         name = group.getName();
324       }
325       else
326       {
327         if (af != null)
328         {
329           name = af.getTitle();
330         }
331         if (name == null || "".equals(name))
332         {
333           name = "Alignment";
334         }
335       }
336     }
337
338     command += "-n " + name.replace(' ', '_') + cmds.SPACE;
339     if (!alignment.isNucleotide())
340     {
341       command += cmds.FORCEAMINO; // TODO check for rna
342     }
343     else
344     {
345       command += cmds.FORCEDNA;
346     }
347
348     command += hmmTemp.getAbsolutePath()
349             + cmds.SPACE + stoTemp.getAbsolutePath() + cmds.SPACE;
350     return cmds.runCommand(command);
351   }
352   
353   /**
354    * Imports the .hmm file produced by hmmbuild.
355    * 
356    * @throws IOException
357    * @throws InterruptedException
358    */
359   private void importData() throws IOException, InterruptedException
360   {
361       HMMFile file = new HMMFile(new FileParse(hmmTemp.getAbsolutePath(),
362               DataSourceType.FILE));
363     SequenceI[] seqs = file.getSeqsAsArray();
364     SequenceI seq = seqs[0];
365     seq.createDatasetSequence();
366     HiddenMarkovModel hmm = file.getHMM();
367     if (group != null)
368     {
369       seq.insertCharAt(0, group.getStartRes(), '-');
370       seq.insertCharAt(group.getEndRes() + 1,
371               alignment.getWidth() - group.getEndRes(), '-');
372       seq.updateHMMMapping();
373       SequenceI topSeq = group.getSequencesInOrder(alignment)[0];
374       int topIndex = alignment.findIndex(topSeq);
375       alignment.insertSequenceAt(topIndex, seq);
376       group.setSeqrep(seq);
377       group.addSequence(seq, false);
378     }
379     else
380     {
381       alignment.insertSequenceAt(0, seq);
382     }
383
384     if (viewport != null)
385     {
386       viewport.alignmentChanged(viewport.getAlignPanel());
387       viewport.getAlignPanel().adjustAnnotationHeight();
388       viewport.updateSequenceIdColours();
389
390       if (viewport.getAlignPanel().alignFrame.getSelectedHMM() == null)
391       {
392         viewport.getAlignPanel().alignFrame.setSelectedHMMSequence(seq);
393       }
394     }
395     hmmTemp.delete();
396     stoTemp.delete();
397   }
398   
399   /**
400    * Runs hmmbuild, and waits for the results to be imported before continuing
401    */
402   public void hmmbuildWaitTillComplete()
403   {
404     Thread loader = new Thread(this);
405     loader.start();
406
407     while (loader.isAlive())
408     {
409       try
410       {
411         Thread.sleep(500);
412       } catch (Exception ex)
413       {
414       }
415     }
416   }
417 }