JAL-2629 hmmbuild runs on the alignment by default
[jalview.git] / src / jalview / hmmer / HMMSearchThread.java
1 package jalview.hmmer;
2
3 import jalview.bin.Cache;
4 import jalview.datamodel.Alignment;
5 import jalview.datamodel.AlignmentI;
6 import jalview.datamodel.HiddenMarkovModel;
7 import jalview.datamodel.SequenceI;
8 import jalview.gui.AlignFrame;
9 import jalview.gui.JvOptionPane;
10 import jalview.gui.Preferences;
11 import jalview.io.DataSourceType;
12 import jalview.io.FileParse;
13 import jalview.io.StockholmFile;
14 import jalview.util.MessageManager;
15 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
16 import jalview.ws.params.ArgumentI;
17 import jalview.ws.params.simple.BooleanOption;
18
19 import java.io.BufferedReader;
20 import java.io.File;
21 import java.io.FileReader;
22 import java.io.IOException;
23 import java.io.PrintWriter;
24 import java.util.ArrayList;
25 import java.util.List;
26
27 import javax.swing.JOptionPane;
28
29 public class HMMSearchThread implements Runnable
30 {
31   /**
32    * feature settings from view that job was associated with
33    */
34   protected FeatureRendererSettings featureSettings = null;
35
36   /**
37    * Object containing frequently used commands.
38    */
39   HMMERCommands cmds = new HMMERCommands();
40
41   AlignFrame af;
42
43   HiddenMarkovModel hmm;
44
45   boolean newFrame, realign = false, trim = false;
46
47   Integer numberOfSequences = null;
48
49   long barID;
50
51   SequenceI hmmSeq;
52
53   List<ArgumentI> params;
54
55   File hmmTemp = null;
56
57   File inputAlignmentTemp = null;
58
59   File inputTableTemp = null;
60
61   File databaseFile = null;
62
63
64
65   SequenceI[] seqs;
66
67
68   /**
69    * Constructor for the HMMSearchThread. If create new frame is set to true, a
70    * new frame will be created.
71    * 
72    * @param af
73    * @param createNewFrame
74    */
75   public HMMSearchThread(AlignFrame af, boolean createNewFrame,
76           List<ArgumentI> args)
77   {
78     this.af = af;
79     newFrame = createNewFrame;
80     featureSettings = af.getFeatureRenderer().getSettings();
81     params = args;
82   }
83
84   /**
85    * Runs the HMMSearchThread: the data on the alignment or group is exported,
86    * then the command is executed in the command line and then the data is
87    * imported and displayed in a new frame (if true).
88    */
89   @Override
90   public void run()
91   {
92     if (af.getSelectedHMM() == null)
93     {
94       JOptionPane.showMessageDialog(af,
95               MessageManager.getString("warn.no_selected_hmm"));
96       return;
97     }
98     else
99     {
100       hmm = af.getSelectedHMM();
101     }
102
103     hmmSeq = af.getSelectedHMMSequence();
104     barID = System.currentTimeMillis();
105     af.setProgressBar(MessageManager.getString("status.running_hmmsearch"),
106             barID);
107     cmds.HMMERFOLDER = Cache.getProperty(Preferences.HMMER_PATH);
108
109     try
110     {
111       createTemporaryFiles();
112     } catch (IOException e2)
113     {
114       e2.printStackTrace();
115     }
116     try
117     {
118       cmds.exportData(null, null, hmm, hmmTemp.getAbsoluteFile());
119     } catch (IOException e1)
120     {
121       e1.printStackTrace();
122     }
123     try
124     {
125       boolean ran = runCommand();
126       if (!ran)
127       {
128         JvOptionPane.showInternalMessageDialog(af,
129                 MessageManager.getString("warn.hmmsearch_failed"));
130         return;
131       }
132     } catch (IOException | InterruptedException e)
133     {
134       e.printStackTrace();
135     }
136     try
137     {
138       importData();
139     } catch (IOException | InterruptedException e)
140     {
141       // TODO Auto-generated catch block
142       e.printStackTrace();
143     }
144
145     af.setProgressBar(MessageManager.getString("status.running_hmmsearch"),
146             barID);
147
148   }
149
150   /**
151    * Creates temporary files for exporting and importing the data.
152    * 
153    * @throws IOException
154    */
155   private void createTemporaryFiles() throws IOException
156   {
157     hmmTemp = File.createTempFile("hmm", ".hmm");
158     hmmTemp.deleteOnExit();
159     inputAlignmentTemp = File.createTempFile("inputAl", ".sto");
160     inputAlignmentTemp.deleteOnExit();
161     inputTableTemp = File.createTempFile("buffer", ".sto");
162     inputTableTemp.deleteOnExit();
163   }
164
165   /**
166    * Executes the hmmsearch command in the command line.
167    * 
168    * @return
169    * @throws IOException
170    * @throws InterruptedException
171    */
172   private boolean runCommand() throws IOException, InterruptedException
173   {
174     Boolean dbFound = false;
175     String dbPath = "";
176     File file = new File(cmds.HMMERFOLDER + "/hmmsearch");
177     if (!file.canExecute())
178     {
179       file = new File(cmds.HMMERFOLDER + "/hmmsearch.exe");
180       {
181         if (!file.canExecute())
182         {
183           return false;
184         }
185       }
186     }
187
188     String command = cmds.HMMERFOLDER + "/hmmsearch -o "
189             + inputTableTemp.getAbsolutePath() + " -A "
190             + inputAlignmentTemp.getAbsolutePath() + cmds.SPACE;
191     if (params != null)
192     {
193       for (ArgumentI arg : params)
194       {
195         String name = arg.getName();
196         switch (name)
197         {
198         case "Number of Results to Return":
199           numberOfSequences = Integer.parseInt(arg.getValue());
200           break;
201         case "Automatically Align Fetched Sequences":
202           if ("Automatically Align Fetched Sequences"
203                   .equals(arg.getValue()))
204           {
205             realign = true;
206           }
207           break;
208         case "Return Accessions":
209           if ("Return Accessions".equals(arg.getValue()))
210           {
211             command += "--acc ";
212           }
213           break;
214         case "Sequence E-value Cutoff":
215           command += "--incE " + arg.getValue() + cmds.SPACE;
216           break;
217         case "Sequence Score Threshold":
218           command += "-incT " + arg.getValue() + cmds.SPACE;
219           break;
220         case "Domain E-value Threshold":
221           command += "--incdomE " + arg.getValue() + cmds.SPACE;
222           break;
223         case "Domain Score Threshold":
224           command += "--incdomT " + arg.getValue() + cmds.SPACE;
225           break;
226         case "Trim Non-Matching Termini":
227           trim = true;
228           break;
229         case "Database":
230           dbFound = true;
231           dbPath = arg.getValue();
232           if (!MessageManager.getString("label.this_alignment")
233                   .equals(dbPath))
234           {
235             databaseFile = new File(dbPath);
236           }
237         }
238
239       }
240     }
241
242     if (dbFound == false || MessageManager.getString("label.this_alignment")
243             .equals(dbPath))
244     {
245       AlignmentI alignment = af.getViewport().getAlignment();
246       AlignmentI copy = new Alignment(alignment);
247       copy.getHMMConsensusSequences(true);
248       StockholmFile stoFile = new StockholmFile(copy);
249       stoFile.setSeqs(copy.getSequencesArray());
250       String alignmentString = stoFile.print();
251       databaseFile = File.createTempFile("database", ".sto");
252       databaseFile.deleteOnExit();
253       PrintWriter writer = new PrintWriter(databaseFile);
254       writer.print(alignmentString);
255       writer.close();
256     }
257
258     command += hmmTemp.getAbsolutePath() + cmds.SPACE
259             + databaseFile.getAbsolutePath();
260     return cmds.runCommand(command);
261   }
262
263   /**
264    * Imports the data from the temporary file to which the output of hmmsearch
265    * is directed.
266    */
267   private void importData() throws IOException, InterruptedException
268   {
269     BufferedReader br = new BufferedReader(
270             new FileReader(inputAlignmentTemp));
271     if (br.readLine() == null)
272     {
273       JOptionPane.showMessageDialog(af,
274               MessageManager.getString("label.no_sequences_found"));
275       return;
276     }
277     StockholmFile file = new StockholmFile(new FileParse(
278             inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE));
279     seqs = file.getSeqsAsArray();
280
281     readTable();
282
283     SequenceI[] hmmAndSeqs;
284     if (numberOfSequences != null && numberOfSequences < seqs.length)
285     {
286       hmmAndSeqs = new SequenceI[numberOfSequences + 1];
287     }
288     else
289     {
290       hmmAndSeqs = new SequenceI[seqs.length + 1];
291     }
292     hmmAndSeqs[0] = hmmSeq;
293
294     if (numberOfSequences != null && seqs.length > numberOfSequences)
295     {
296       System.arraycopy(seqs, 0, hmmAndSeqs, 1, numberOfSequences);
297     }
298     else
299     {
300       System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqs.length);
301     }
302
303     AlignmentI alignment = new Alignment(hmmAndSeqs);
304     AlignFrame frame = new AlignFrame(alignment, 1, 1);
305     frame.setSelectedHMMSequence(hmmSeq);
306     List<ArgumentI> alignArgs = new ArrayList<>();
307     if (trim)
308     {
309       alignArgs.add(new BooleanOption(
310               MessageManager.getString("label.trim_termini"),
311               MessageManager.getString("label.trim_termini_desc"), true,
312               true, true, null));
313     }
314     HMMAlignThread hmmalign = new HMMAlignThread(frame, true, alignArgs);
315     hmmalign.hmmalignWaitTillComplete();
316     frame = null;
317     hmmTemp.delete();
318     inputAlignmentTemp.delete();
319     inputTableTemp.delete();
320   }
321
322   /**
323    * Runs hmmsearch, and waits for the results to be imported before continuing
324    */
325   public void hmmsearchWaitTillComplete()
326   {
327     Thread loader = new Thread(this);
328     loader.start();
329
330     while (loader.isAlive())
331     {
332       try
333       {
334         Thread.sleep(500);
335       } catch (Exception ex)
336       {
337       }
338     }
339
340   }
341
342   public void readTable() throws IOException
343   {
344
345     /*
346     BufferedReader br = new BufferedReader(new FileReader(inputTableTemp));
347     String line = "";
348     while (!line.startsWith("Query:"))
349     {
350       line = br.readLine();
351     }
352     for (int i = 0; i < 4; i++)
353     {
354       br.readLine();
355     }
356     
357     
358     int index = 0;
359     while (!"  ------ inclusion threshold ------".equals(line))
360     {
361       Scanner scanner = new Scanner(line);
362     
363       String str = scanner.next();
364       AlignmentAnnotation annots = new AlignmentAnnotation("", "", null);
365       annots.setScore(Double.parseDouble(str));
366       seqs[index].addAlignmentAnnotation(annots);
367     
368       scanner.close();
369     }
370     
371     br.close();
372     */
373
374   }
375
376 }