f940fbb26c2a5f08e1f066050516f46341781153
[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           cmds.exportData(newArr, stoTemp, null, null);
238           jalview.analysis.SeqsetUtils.deuniquify(cmds.hash, array);
239
240       } catch (FileNotFoundException e)
241       {
242         // TODO Auto-generated catch block
243         e.printStackTrace();
244
245       }
246       try
247       {
248           boolean ran = runCommand();
249           if (!ran)
250           {
251             return;
252           }
253       } catch (IOException | InterruptedException e)
254       {
255         // TODO Auto-generated catch block
256         e.printStackTrace();
257       }
258       try
259       {
260
261         importData();
262       } catch (IOException | InterruptedException e)
263       {
264         // TODO Auto-generated catch block
265         e.printStackTrace();
266       }
267       } catch (Exception e)
268       {
269         e.printStackTrace();
270     }
271   }
272
273   
274
275   /**
276    * Executes the hmmbuild command in the command line.
277    * 
278    * @return
279    * @throws IOException
280    * @throws InterruptedException
281    */
282   private boolean runCommand() throws IOException, InterruptedException
283   {
284     File file = new File(cmds.HMMERFOLDER + "/hmmbuild");
285     if (!file.canExecute())
286     {
287       file = new File(cmds.HMMERFOLDER + "/hmmbuild.exe");
288       {
289         if (!file.canExecute())
290         {
291           if (af != null)
292           {
293             JvOptionPane.showInternalMessageDialog(af,
294                     MessageManager.getString("warn.hmmbuild_failed"));
295           }
296           return false;
297         }
298       }
299     }
300     String command = cmds.HMMERFOLDER + cmds.HMMBUILD + cmds.SPACE;
301     String name = null;
302
303     if (params != null)
304     {
305       for (ArgumentI arg : params)
306       {
307         String argName = arg.getName();
308         switch (argName)
309         {
310         case "HMM Name":
311           name = arg.getValue();
312           name = name.trim();
313           break;
314         case "Use Reference Annotation":
315           command += "--hand ";
316           break;
317
318         }
319
320       }
321     }
322
323     if (forGroup && multiJob)
324     {
325       name = group.getName() + "_HMM";
326     }
327
328
329     if (name == null || "".equals(name))
330     {
331         if (af != null)
332         {
333           name = af.getTitle();
334         }
335         if (name == null || "".equals(name))
336         {
337           name = "Alignment";
338         }
339
340     }
341
342     command += "-n " + name.replace(' ', '_') + cmds.SPACE;
343     if (!alignment.isNucleotide())
344     {
345       command += cmds.FORCEAMINO; // TODO check for rna
346     }
347     else
348     {
349       command += cmds.FORCEDNA;
350     }
351
352     command += hmmTemp.getAbsolutePath()
353             + cmds.SPACE + stoTemp.getAbsolutePath() + cmds.SPACE;
354     return cmds.runCommand(command);
355   }
356   
357   /**
358    * Imports the .hmm file produced by hmmbuild.
359    * 
360    * @throws IOException
361    * @throws InterruptedException
362    */
363   private void importData() throws IOException, InterruptedException
364   {
365       HMMFile file = new HMMFile(new FileParse(hmmTemp.getAbsolutePath(),
366               DataSourceType.FILE));
367     SequenceI[] seqs = file.getSeqsAsArray();
368     SequenceI seq = seqs[0];
369     seq.createDatasetSequence();
370     HiddenMarkovModel hmm = file.getHMM();
371     if (group != null)
372     {
373       seq.insertCharAt(0, group.getStartRes(), '-');
374       seq.insertCharAt(group.getEndRes() + 1,
375               alignment.getWidth() - group.getEndRes() - 1, '-');
376       seq.updateHMMMapping();
377       SequenceI topSeq = group.getSequencesInOrder(alignment)[0];
378       int topIndex = alignment.findIndex(topSeq);
379       alignment.insertSequenceAt(topIndex, seq);
380       group.setSeqrep(seq);
381       group.addSequence(seq, false);
382     }
383     else
384     {
385       alignment.insertSequenceAt(0, seq);
386     }
387
388     if (viewport != null)
389     {
390       viewport.alignmentChanged(viewport.getAlignPanel());
391       viewport.getAlignPanel().adjustAnnotationHeight();
392       viewport.updateSequenceIdColours();
393
394       if (viewport.getAlignPanel().alignFrame.getSelectedHMM() == null)
395       {
396         viewport.getAlignPanel().alignFrame.setSelectedHMMSequence(seq);
397       }
398     }
399     hmmTemp.delete();
400     stoTemp.delete();
401   }
402   
403   /**
404    * Runs hmmbuild, and waits for the results to be imported before continuing
405    */
406   public void hmmbuildWaitTillComplete()
407   {
408     Thread loader = new Thread(this);
409     loader.start();
410
411     while (loader.isAlive())
412     {
413       try
414       {
415         Thread.sleep(500);
416       } catch (Exception ex)
417       {
418       }
419     }
420   }
421 }