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