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