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