package jalview.hmmer; import jalview.bin.Cache; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.Desktop; import jalview.gui.JvOptionPane; import jalview.io.DataSourceType; import jalview.io.FileParse; import jalview.io.StockholmFile; import jalview.util.FileUtils; import jalview.util.MessageManager; import jalview.ws.params.ArgumentI; 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 javax.swing.JOptionPane; public class JackHMMER extends Search { SequenceI seq = null; /** * Constructor for the JackhmmerThread * * @param af */ public JackHMMER(AlignFrame af, List args) { super(af, args); } /** * Runs the JackhmmerThread: 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() { seq = getSequence(); if (seq == null) { // shouldn't happen if we got this far Cache.log.error("Error: no sequence for jackhmmer"); return; } long msgId = System.currentTimeMillis(); af.setProgressBar(MessageManager.getString("status.running_search"), msgId); try { File seqFile = FileUtils.createTempFile("seq", ".sto"); File hitsAlignmentFile = FileUtils.createTempFile("hitAlignment", ".sto"); File searchOutputFile = FileUtils.createTempFile("searchOutput", ".txt"); exportStockholm(new SequenceI[] { seq }, seqFile.getAbsoluteFile(), null); boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, seqFile); if (!ran) { JvOptionPane.showInternalMessageDialog(af, MessageManager .formatMessage("warn.command_failed", "jackhmmer")); return; } importData(hitsAlignmentFile, seqFile, 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 jackhmmer search with the given sequence 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 seqFile * * @return * @throws IOException */ private boolean runCommand(File searchOutputFile, File hitsAlignmentFile, File seqFile) throws IOException { String command = getCommandPath(JACKHMMER); if (command == null) { return false; } List args = new ArrayList<>(); args.add(command); buildArguments(args, searchOutputFile, hitsAlignmentFile, seqFile); return runCommand(args); } /** * Imports the data from the temporary file to which the output of jackhmmer was * directed. */ private void importData(File inputAlignmentTemp, File seqTemp, 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(); readDomainTable(searchOutputFile, true); if (searchAlignment) { recoverSequences(sequencesHash, seqs); } int seqCount = seqs.length; AlignmentI al = new Alignment(seqs); AlignFrame alignFrame = new AlignFrame(al, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); String ttl = "jackhmmer search of " + databaseName + " using " + seqs[0].getName(); Desktop.addInternalFrame(alignFrame, ttl, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); seqTemp.delete(); inputAlignmentTemp.delete(); searchOutputFile.delete(); } finally { if (br != null) { br.close(); } } } }