3 import jalview.bin.Cache;
4 import jalview.bin.Console;
5 import jalview.datamodel.Alignment;
6 import jalview.datamodel.AlignmentAnnotation;
7 import jalview.datamodel.AlignmentI;
8 import jalview.datamodel.Annotation;
9 import jalview.datamodel.HiddenMarkovModel;
10 import jalview.datamodel.SequenceI;
11 import jalview.gui.AlignFrame;
12 import jalview.gui.Desktop;
13 import jalview.gui.JvOptionPane;
14 import jalview.io.DataSourceType;
15 import jalview.io.FileParse;
16 import jalview.io.StockholmFile;
17 import jalview.util.FileUtils;
18 import jalview.util.MessageManager;
19 import jalview.ws.params.ArgumentI;
20 import jalview.ws.params.simple.BooleanOption;
21 import jalview.ws.params.simple.Option;
23 import java.io.BufferedReader;
25 import java.io.FileReader;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
31 import javax.swing.JOptionPane;
33 public class HMMSearch extends Search
36 boolean realign = false;
40 boolean returnNoOfNewSeqs = false;
42 int seqsToReturn = Integer.MAX_VALUE;
46 * Constructor for the HMMSearchThread
50 public HMMSearch(AlignFrame af, List<ArgumentI> args)
56 * Runs the HMMSearchThread: the data on the alignment or group is exported,
57 * then the command is executed in the command line and then the data is
58 * imported and displayed in a new frame. Call this method directly to execute
59 * synchronously, or via start() in a new Thread for asynchronously.
64 HiddenMarkovModel hmm = getHmmProfile();
67 // shouldn't happen if we got this far
68 Console.error("Error: no hmm for hmmsearch");
72 SequenceI hmmSeq = hmm.getConsensusSequence();
73 long msgId = System.currentTimeMillis();
74 af.setProgressBar(MessageManager.getString("status.running_search"),
79 File hmmFile = FileUtils.createTempFile("hmm", ".hmm");
80 File hitsAlignmentFile = FileUtils.createTempFile("hitAlignment",
82 File searchOutputFile = FileUtils.createTempFile("searchOutput",
85 exportHmm(hmm, hmmFile.getAbsoluteFile());
87 boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, hmmFile);
90 JvOptionPane.showInternalMessageDialog(af, MessageManager
91 .formatMessage("warn.command_failed", "hmmsearch"));
95 importData(hmmSeq, hitsAlignmentFile, hmmFile, searchOutputFile);
96 // TODO make realignment of search results a step at this level
97 // and make it conditional on this.realign
98 } catch (IOException | InterruptedException e)
104 af.setProgressBar("", msgId);
109 * Executes an hmmsearch with the given hmm as input. The database to be
110 * searched is a local file as specified by the 'Database' parameter, or the
111 * current alignment (written to file) if none is specified.
113 * @param searchOutputFile
114 * @param hitsAlignmentFile
118 * @throws IOException
120 private boolean runCommand(File searchOutputFile, File hitsAlignmentFile,
121 File hmmFile) throws IOException
123 String command = getCommandPath(HMMSEARCH);
129 List<String> args = new ArrayList<>();
131 buildArguments(args, searchOutputFile, hitsAlignmentFile, hmmFile);
133 return runCommand(args);
138 * Imports the data from the temporary file to which the output of hmmsearch
139 * was directed. The results are optionally realigned using hmmalign.
143 private void importData(SequenceI hmmSeq, File inputAlignmentTemp,
144 File hmmTemp, File searchOutputFile)
145 throws IOException, InterruptedException
147 BufferedReader br = new BufferedReader(
148 new FileReader(inputAlignmentTemp));
151 if (br.readLine() == null)
153 JOptionPane.showMessageDialog(af,
154 MessageManager.getString("label.no_sequences_found"));
157 StockholmFile file = new StockholmFile(new FileParse(
158 inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE));
159 seqs = file.getSeqsAsArray();
161 readDomainTable(searchOutputFile, false);
165 recoverSequences(sequencesHash, seqs);
168 // look for PP cons and ref seq in alignment only annotation
169 AlignmentAnnotation modelpos = null, ppcons = null;
170 for (AlignmentAnnotation aa : file.getAnnotations())
172 if (aa.sequenceRef == null)
174 if (aa.label.equals("Reference Positions")) // RF feature type in
179 if (aa.label.equals("Posterior Probability"))
187 int seqCount = Math.min(seqs.length, seqsToReturn);
188 SequenceI[] hmmAndSeqs = new SequenceI[seqCount + 1];
189 hmmSeq = hmmSeq.deriveSequence(); // otherwise all bad things happen
190 hmmAndSeqs[0] = hmmSeq;
191 System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount);
192 if (modelpos != null)
194 // TODO need - get ungapped sequence method
196 hmmSeq.getDatasetSequence().getSequenceAsString());
197 Annotation[] refpos = modelpos.annotations;
198 // insert gaps to match with refseq positions
199 int gc = 0, lcol = 0;
200 for (int c = 0; c < refpos.length; c++)
202 if (refpos[c] != null && ("x".equals(refpos[c].displayCharacter)))
206 hmmSeq.insertCharAt(lcol + 1, gc, '-');
220 realignResults(hmmAndSeqs);
224 AlignmentI al = new Alignment(hmmAndSeqs);
227 al.addAnnotation(ppcons);
229 if (modelpos != null)
231 al.addAnnotation(modelpos);
233 AlignFrame alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH,
234 AlignFrame.DEFAULT_HEIGHT);
235 String ttl = "hmmSearch of " + databaseName + " using "
237 Desktop.addInternalFrame(alignFrame, ttl, AlignFrame.DEFAULT_WIDTH,
238 AlignFrame.DEFAULT_HEIGHT);
240 if (returnNoOfNewSeqs)
242 int nNew = checkForNewSequences();
243 JvOptionPane.showMessageDialog(af.alignPanel, nNew + " "
244 + MessageManager.getString("label.new_returned"));
251 inputAlignmentTemp.delete();
252 searchOutputFile.delete();
262 private int checkForNewSequences()
264 int nNew = seqs.length;
266 for (SequenceI resultSeq : seqs)
268 for (SequenceI aliSeq : alignment.getSequencesArray())
270 if (resultSeq.getName().equals(aliSeq.getName()))
283 * Realigns the given sequences using hmmalign, to the HMM profile sequence
284 * which is the first in the array, and opens the results in a new frame
288 protected void realignResults(SequenceI[] hmmAndSeqs)
291 * and align the search results to the HMM profile
293 AlignmentI al = new Alignment(hmmAndSeqs);
294 AlignFrame frame = new AlignFrame(al, 1, 1);
295 List<ArgumentI> alignArgs = new ArrayList<>();
296 String alignTo = hmmAndSeqs[0].getName();
297 List<String> options = Collections.singletonList(alignTo);
298 Option option = new Option(MessageManager.getString("label.use_hmm"),
299 "", true, alignTo, alignTo, options, null);
300 alignArgs.add(option);
303 alignArgs.add(new BooleanOption(
304 MessageManager.getString(TRIM_TERMINI_KEY),
305 MessageManager.getString("label.trim_termini_desc"), true,
308 HmmerCommand hmmalign = new HMMAlign(frame, alignArgs);
311 if (returnNoOfNewSeqs)
313 int nNew = checkForNewSequences();
314 JvOptionPane.showMessageDialog(frame.alignPanel,
315 nNew + " " + MessageManager.getString("label.new_returned"));