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