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