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 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 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 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(); } }