package jalview.hmmer; import jalview.bin.Cache; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.HiddenMarkovModel; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.JvOptionPane; import jalview.gui.Preferences; import jalview.io.DataSourceType; import jalview.io.FileParse; import jalview.io.StockholmFile; import jalview.util.MessageManager; import jalview.viewmodel.seqfeatures.FeatureRendererSettings; import jalview.ws.params.ArgumentI; import jalview.ws.params.simple.BooleanOption; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import javax.swing.JOptionPane; public class HMMSearchThread implements Runnable { /** * feature settings from view that job was associated with */ protected FeatureRendererSettings featureSettings = null; /** * Object containing frequently used commands. */ HMMERCommands cmds = new HMMERCommands(); AlignFrame af; HiddenMarkovModel hmm; boolean newFrame, realign = false, trim = false; Integer numberOfSequences = null; long barID; SequenceI hmmSeq; List params; File hmmTemp = null; File inputAlignmentTemp = null; File inputTableTemp = null; File databaseFile = null; SequenceI[] seqs; /** * Constructor for the HMMSearchThread. If create new frame is set to true, a * new frame will be created. * * @param af * @param createNewFrame */ public HMMSearchThread(AlignFrame af, boolean createNewFrame, List args) { this.af = af; newFrame = createNewFrame; featureSettings = af.getFeatureRenderer().getSettings(); params = 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 (if true). */ @Override public void run() { if (af.getSelectedHMM() == null) { JOptionPane.showMessageDialog(af, MessageManager.getString("warn.no_selected_hmm")); return; } else { hmm = af.getSelectedHMM(); } hmmSeq = af.getSelectedHMMSequence(); barID = System.currentTimeMillis(); af.setProgressBar(MessageManager.getString("status.running_hmmsearch"), barID); cmds.HMMERFOLDER = Cache.getProperty(Preferences.HMMER_PATH); try { createTemporaryFiles(); } catch (IOException e2) { e2.printStackTrace(); } try { cmds.exportData(null, null, hmm, hmmTemp.getAbsoluteFile()); } catch (IOException e1) { e1.printStackTrace(); } try { boolean ran = runCommand(); if (!ran) { JvOptionPane.showInternalMessageDialog(af, MessageManager.getString("warn.hmmsearch_failed")); return; } } catch (IOException | InterruptedException e) { e.printStackTrace(); } try { importData(); } catch (IOException | InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } af.setProgressBar(MessageManager.getString("status.running_hmmsearch"), barID); } /** * Creates temporary files for exporting and importing the data. * * @throws IOException */ private void createTemporaryFiles() throws IOException { hmmTemp = File.createTempFile("hmm", ".hmm"); hmmTemp.deleteOnExit(); inputAlignmentTemp = File.createTempFile("inputAl", ".sto"); inputAlignmentTemp.deleteOnExit(); inputTableTemp = File.createTempFile("buffer", ".sto"); inputTableTemp.deleteOnExit(); } /** * Executes the hmmsearch command in the command line. * * @return * @throws IOException * @throws InterruptedException */ private boolean runCommand() throws IOException, InterruptedException { Boolean dbFound = false; String dbPath = ""; File file = new File(cmds.HMMERFOLDER + "/hmmsearch"); if (!file.canExecute()) { file = new File(cmds.HMMERFOLDER + "/hmmsearch.exe"); { if (!file.canExecute()) { return false; } } } String command = cmds.HMMERFOLDER + "/hmmsearch -o " + inputTableTemp.getAbsolutePath() + " -A " + inputAlignmentTemp.getAbsolutePath() + cmds.SPACE; if (params != null) { for (ArgumentI arg : params) { String name = arg.getName(); switch (name) { case "Number of Results to Return": numberOfSequences = Integer.parseInt(arg.getValue()); break; case "Automatically Align Fetched Sequences": if ("Automatically Align Fetched Sequences" .equals(arg.getValue())) { realign = true; } break; case "Return Accessions": if ("Return Accessions".equals(arg.getValue())) { command += "--acc "; } break; case "Sequence E-value Cutoff": command += "--incE " + arg.getValue() + cmds.SPACE; break; case "Sequence Score Threshold": command += "-incT " + arg.getValue() + cmds.SPACE; break; case "Domain E-value Threshold": command += "--incdomE " + arg.getValue() + cmds.SPACE; break; case "Domain Score Threshold": command += "--incdomT " + arg.getValue() + cmds.SPACE; break; case "Trim Non-Matching Termini": trim = true; break; case "Database": dbFound = true; dbPath = arg.getValue(); if (!MessageManager.getString("label.this_alignment") .equals(dbPath)) { databaseFile = new File(dbPath); } } } } if (dbFound == false || MessageManager.getString("label.this_alignment") .equals(dbPath)) { AlignmentI alignment = af.getViewport().getAlignment(); AlignmentI copy = new Alignment(alignment); copy.getHMMConsensusSequences(true); StockholmFile stoFile = new StockholmFile(copy); stoFile.setSeqs(copy.getSequencesArray()); String alignmentString = stoFile.print(); databaseFile = File.createTempFile("database", ".sto"); databaseFile.deleteOnExit(); PrintWriter writer = new PrintWriter(databaseFile); writer.print(alignmentString); writer.close(); } command += hmmTemp.getAbsolutePath() + cmds.SPACE + databaseFile.getAbsolutePath(); return cmds.runCommand(command); } /** * Imports the data from the temporary file to which the output of hmmsearch * is directed. */ private void importData() throws IOException, InterruptedException { StockholmFile file = new StockholmFile(new FileParse( inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE)); seqs = file.getSeqsAsArray(); readTable(); SequenceI[] hmmAndSeqs; if (numberOfSequences != null && numberOfSequences < seqs.length) { hmmAndSeqs = new SequenceI[numberOfSequences + 1]; } else { hmmAndSeqs = new SequenceI[seqs.length + 1]; } AlignmentAnnotation[] list = hmmSeq.getAnnotation(); for (AlignmentAnnotation annot : list) { if ("HMM".equals(annot.getCalcId())) { hmmSeq.removeAlignmentAnnotation(annot); } } hmmSeq.setHasInfo(false); hmmAndSeqs[0] = hmmSeq; if (numberOfSequences != null && seqs.length > numberOfSequences) { System.arraycopy(seqs, 0, hmmAndSeqs, 1, numberOfSequences); } else { System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqs.length); } 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)); } HMMAlignThread hmmalign = new HMMAlignThread(frame, true, alignArgs); hmmalign.hmmalignWaitTillComplete(); frame = null; hmmTemp.delete(); inputAlignmentTemp.delete(); inputTableTemp.delete(); } /** * Runs hmmsearch, and waits for the results to be imported before continuing */ public void hmmsearchWaitTillComplete() { Thread loader = new Thread(this); loader.start(); while (loader.isAlive()) { try { Thread.sleep(500); } catch (Exception ex) { } } } public void readTable() throws IOException { /* BufferedReader br = new BufferedReader(new FileReader(inputTableTemp)); String line = ""; while (!line.startsWith("Query:")) { line = br.readLine(); } for (int i = 0; i < 4; i++) { br.readLine(); } int index = 0; while (!" ------ inclusion threshold ------".equals(line)) { Scanner scanner = new Scanner(line); String str = scanner.next(); AlignmentAnnotation annots = new AlignmentAnnotation("", "", null); annots.setScore(Double.parseDouble(str)); seqs[index].addAlignmentAnnotation(annots); scanner.close(); } br.close(); */ } }