--- /dev/null
+package jalview.hmmer;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Annotation;
+import jalview.datamodel.HiddenMarkovModel;
+import jalview.datamodel.SequenceI;
+import jalview.gui.AlignFrame;
+import jalview.gui.JvOptionPane;
+import jalview.io.DataSourceType;
+import jalview.io.FileParse;
+import jalview.io.StockholmFile;
+import jalview.util.MessageManager;
+import jalview.ws.params.ArgumentI;
+import jalview.ws.params.simple.BooleanOption;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import javax.swing.JOptionPane;
+
+public class HMMSearch extends HmmerCommand
+{
+ static final String HMMSEARCH = "hmmsearch";
+
+ boolean realign = false;
+
+ boolean trim = false;
+
+ int seqsToReturn = Integer.MAX_VALUE;
+
+ SequenceI[] seqs;
+
+ /**
+ * Constructor for the HMMSearchThread
+ *
+ * @param af
+ */
+ public HMMSearch(AlignFrame af, List<ArgumentI> args)
+ {
+ super(af, args);
+ }
+
+ /**
+ * Runs the HMMSearchThread: the data on the alignment or group is exported,
+ * then the command is executed in the command line and then the data is
+ * imported and displayed in a new frame. Call this method directly to execute
+ * synchronously, or via start() in a new Thread for asynchronously.
+ */
+ @Override
+ public void run()
+ {
+ HiddenMarkovModel hmm = af.getSelectedHMM();
+ if (hmm == null)
+ {
+ JOptionPane.showMessageDialog(af,
+ MessageManager.getString("warn.no_selected_hmm"));
+ return;
+ }
+
+ SequenceI hmmSeq = af.getSelectedHMMSequence();
+ long msgId = System.currentTimeMillis();
+ af.setProgressBar(MessageManager.getString("status.running_hmmsearch"),
+ msgId);
+
+ try
+ {
+ File hmmFile = createTempFile("hmm", ".hmm");
+ File hitsAlignmentFile = createTempFile("hitAlignment", ".sto");
+ File searchOutputFile = createTempFile("searchOutput", ".sto");
+
+ exportHmm(hmm, hmmFile.getAbsoluteFile());
+
+ boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, hmmFile);
+ if (!ran)
+ {
+ JvOptionPane.showInternalMessageDialog(af,
+ MessageManager.getString("warn.hmmsearch_failed"));
+ return;
+ }
+
+ importData(hmmSeq, hitsAlignmentFile, hmmFile, searchOutputFile);
+ // TODO make realignment of search results a step at this level
+ // and make it conditional on this.realign
+ } catch (IOException | InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ finally
+ {
+ af.setProgressBar("", msgId);
+ }
+ }
+
+ /**
+ * Executes an hmmsearch with the given hmm as input. The database to be
+ * searched is a local file as specified by the 'Database' parameter, or the
+ * current alignment (written to file) if none is specified.
+ *
+ * @param searchOutputFile
+ * @param hitsAlignmentFile
+ * @param hmmFile
+ *
+ * @return
+ * @throws IOException
+ */
+ private boolean runCommand(File searchOutputFile, File hitsAlignmentFile,
+ File hmmFile) throws IOException
+ {
+ String command = getCommandPath(HMMSEARCH);
+ if (command == null)
+ {
+ return false;
+ }
+
+ List<String> args = new ArrayList<>();
+ args.add(command);
+ args.add("-o");
+ args.add(searchOutputFile.getAbsolutePath());
+ args.add("-A");
+ args.add(hitsAlignmentFile.getAbsolutePath());
+
+ boolean dbFound = false;
+ String dbPath = "";
+ File databaseFile = null;
+
+ if (params != null)
+ {
+ for (ArgumentI arg : params)
+ {
+ String name = arg.getName();
+ if (MessageManager.getString("label.number_of_results")
+ .equals(name))
+ {
+ seqsToReturn = Integer.parseInt(arg.getValue());
+ }
+ else if (MessageManager.getString("label.auto_align_seqs")
+ .equals(name))
+ {
+ realign = true; // TODO: not used
+ }
+ else if (MessageManager.getString("label.use_accessions")
+ .equals(name))
+ {
+ args.add("--acc");
+ }
+ else if (MessageManager.getString("label.seq_e_value").equals(name))
+ {
+ args.add("--incE");
+ args.add(arg.getValue());
+ }
+ else if (MessageManager.getString("label.seq_score").equals(name))
+ {
+ args.add("-incT");
+ args.add(arg.getValue());
+ }
+ else if (MessageManager.getString("label.dom_e_value_desc")
+ .equals(name))
+ {
+ args.add("--incdomE");
+ args.add(arg.getValue());
+ }
+ else if (MessageManager.getString("label.dom_score").equals(name))
+ {
+ args.add("--incdomT");
+ args.add(arg.getValue());
+ }
+ else if (MessageManager.getString("label.trim_termini")
+ .equals(name))
+ {
+ trim = true;
+ }
+ else if (MessageManager.getString("label.database").equals(name))
+ {
+ dbFound = true;
+ dbPath = arg.getValue();
+ if (!MessageManager.getString("label.this_alignment")
+ .equals(dbPath))
+ {
+ databaseFile = new File(dbPath);
+ }
+ }
+ }
+ }
+
+ if (!dbFound || MessageManager.getString("label.this_alignment")
+ .equals(dbPath))
+ {
+ /*
+ * no external database specified for search, so
+ * export current alignment as 'database' to search
+ */
+ databaseFile = createTempFile("database", ".sto");
+ AlignmentI al = af.getViewport().getAlignment();
+ AlignmentI copy = new Alignment(al);
+ SequenceI hmms = copy.getHmmConsensus();
+ if (hmms != null)
+ {
+ copy.deleteSequence(hmms);
+ }
+ exportStockholm(copy.getSequencesArray(), databaseFile, null);
+ // StockholmFile stoFile = new StockholmFile(copy);
+ // stoFile.setSeqs(copy.getSequencesArray());
+ // String alignmentString = stoFile.print();
+ // PrintWriter writer = new PrintWriter(databaseFile);
+ // writer.print(alignmentString);
+ // writer.close();
+ }
+
+ args.add(hmmFile.getAbsolutePath());
+ args.add(databaseFile.getAbsolutePath());
+
+ return runCommand(args);
+ }
+
+ /**
+ * Imports the data from the temporary file to which the output of hmmsearch
+ * is directed.
+ *
+ * @param hmmSeq
+ */
+ private void importData(SequenceI hmmSeq, File inputAlignmentTemp,
+ File hmmTemp, File searchOutputFile)
+ throws IOException, InterruptedException
+ {
+ BufferedReader br = new BufferedReader(
+ new FileReader(inputAlignmentTemp));
+ try
+ {
+ if (br.readLine() == null)
+ {
+ JOptionPane.showMessageDialog(af,
+ MessageManager.getString("label.no_sequences_found"));
+ return;
+ }
+ StockholmFile file = new StockholmFile(new FileParse(
+ inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE));
+ seqs = file.getSeqsAsArray();
+
+ readTable(searchOutputFile);
+
+ int seqCount = Math.min(seqs.length, seqsToReturn);
+ SequenceI[] hmmAndSeqs = new SequenceI[seqCount + 1];
+ hmmAndSeqs[0] = hmmSeq;
+ System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount);
+
+ AlignmentI alignment = new Alignment(hmmAndSeqs);
+ AlignFrame frame = new AlignFrame(alignment, 1, 1);
+ frame.setSelectedHMMSequence(hmmSeq);
+ List<ArgumentI> alignArgs = new ArrayList<>();
+ if (trim)
+ {
+ alignArgs.add(new BooleanOption(
+ MessageManager.getString("label.trim_termini"),
+ MessageManager.getString("label.trim_termini_desc"), true,
+ true, true, null));
+ }
+ HMMAlign hmmalign = new HMMAlign(frame, alignArgs);
+ hmmalign.run();
+ frame = null;
+ hmmTemp.delete();
+ inputAlignmentTemp.delete();
+ searchOutputFile.delete();
+ } finally
+ {
+ if (br != null)
+ {
+ br.close();
+ }
+ }
+ }
+
+ void readTable(File inputTableTemp) throws IOException
+ {
+ BufferedReader br = new BufferedReader(new FileReader(inputTableTemp));
+ String line = "";
+ while (!line.startsWith("Query:"))
+ {
+ line = br.readLine();
+ }
+ for (int i = 0; i < 5; i++)
+ {
+ line = br.readLine();
+ }
+
+ int index = 0;
+ while (!" ------ inclusion threshold ------".equals(line)
+ && !"".equals(line))
+ {
+ Scanner scanner = new Scanner(line);
+
+ String str = scanner.next(); // full sequence eValue score
+ float eValue = Float.parseFloat(str);
+ int seqLength = seqs[index].getLength();
+ Annotation[] annots = new Annotation[seqLength];
+ for (int j = 0; j < seqLength; j++)
+ {
+ annots[j] = new Annotation(eValue);
+ }
+ AlignmentAnnotation annot = new AlignmentAnnotation("E-value",
+ "Score", annots);
+ annot.setScore(Double.parseDouble(str));
+ annot.setSequenceRef(seqs[index]);
+ seqs[index].addAlignmentAnnotation(annot);
+
+ scanner.close();
+ line = br.readLine();
+ index++;
+ }
+
+ br.close();
+ }
+
+}