package jalview.hmmer; import jalview.analysis.SeqsetUtils; import jalview.datamodel.AlignmentI; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; import jalview.gui.JvOptionPane; import jalview.io.DataSourceType; import jalview.io.FileParse; import jalview.io.HMMFile; import jalview.util.MessageManager; import jalview.ws.params.ArgumentI; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.swing.JOptionPane; public class HMMBuildThread extends HmmerCommand implements Runnable { AlignViewport viewport; boolean multiJob = false; AlignmentI alignment; SequenceGroup group; List params; boolean forGroup = false; File hmmTemp = null; File stoTemp = null; long barID; /** * This is used for validation purposes. Do not use! * * @param viewport */ public HMMBuildThread(AlignmentI alignment) { this.alignment = alignment; forGroup = false; } public HMMBuildThread(AlignFrame af, List args) { this.af = af; viewport = af.getViewport(); params = args; } /** * Builds a HMM from an alignment, then imports and adds it to the alignment. */ @Override public void run() { barID = System.currentTimeMillis(); if (af != null) { af.setProgressBar(MessageManager.getString("status.running_hmmbuild"), barID); } List groups = new ArrayList<>(); if (params != null) { for (ArgumentI arg : params) { String name = arg.getName(); if (MessageManager.getString("label.hmmbuild_for").equals(name)) { String value = arg.getValue(); if ("Alignment".equals(value)) { alignment = viewport.getAlignment(); break; } else if ("All groups and alignment".equals(value)) { alignment = viewport.getAlignment(); groups.addAll(viewport.getAlignment().getGroups()); if (groups.size() > 0) { multiJob = true; } break; } else if ("All groups".equals(value)) { alignment = null; groups = viewport.getAlignment().getGroups(); if (groups.size() > 0) { multiJob = true; } break; } else if ("Selected group".equals(value)) { alignment = null; groups.add(viewport.getSelectionGroup()); break; } } else if (MessageManager.getString("label.use_reference") .equals(name)) { if (!af.getViewport().hasReferenceAnnotation()) { if (af != null) { af.setProgressBar( MessageManager.getString("status.running_hmmbuild"), barID); } JvOptionPane.showInternalMessageDialog(af, MessageManager .getString("warn.no_reference_annotation")); return; } } } } else if (viewport != null) { alignment = viewport.getAlignment(); } if (alignment != null) { forGroup = false; runHMMBuild(); } if (alignment == null) { alignment = viewport.getAlignment(); } if (groups != null && groups.size() > 0) { for (SequenceGroup grp : groups) { group = grp; forGroup = true; runHMMBuild(); } } if (af != null) { af.setProgressBar("", barID); } } private void runHMMBuild() { if (alignment == null && group == null) { JOptionPane.showMessageDialog(af, MessageManager.getString("warn.no_sequence_data")); } try { hmmTemp = File.createTempFile("hmm", ".hmm"); hmmTemp.deleteOnExit(); stoTemp = File.createTempFile("output", ".sto"); stoTemp.deleteOnExit(); } catch (IOException e1) { e1.printStackTrace(); } try { try { SequenceI[] array; List hmmSeqs = null; if (forGroup) { hmmSeqs = group.getHMMConsensusSequences(); if (hmmSeqs.size() > 0) { // todo why this test? means can't re-run hmmbuild on a group? return; } array = group.getSelectionAsNewSequences(alignment); } else { hmmSeqs = alignment.getHMMConsensusSequences(); if (!alignment.isAligned()) { alignment.padGaps(); } array = alignment.getSequencesArray(); } if (array.length < 1) { if (af != null) { JOptionPane.showMessageDialog(af, MessageManager.getString("warn.no_sequence_data")); } return; } /* * copy over sequences excluding hmm consensus sequences */ SequenceI[] newArr = new SequenceI[array.length - hmmSeqs.size()]; int index = 0; for (SequenceI seq : array) { if (!seq.isHMMConsensusSequence()) { newArr[index] = new Sequence(seq); index++; } } uniquifySequences(newArr); if (forGroup) { exportData(newArr, stoTemp, null, null, group); } else { exportData(newArr, stoTemp, null, null, alignment); } SeqsetUtils.deuniquify(hash, array); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { boolean ran = runCommand(); if (!ran) { return; } } catch (IOException | InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { importData(); } catch (IOException | InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (Exception e) { e.printStackTrace(); } } /** * Executes the hmmbuild command in the command line. * * @return * @throws IOException * @throws InterruptedException */ private boolean runCommand() throws IOException, InterruptedException { String binaryPath = getCommandRoot(HMMBUILD); if (binaryPath == null) { return false; } String command = binaryPath + SPACE; String name = null; if (params != null) { for (ArgumentI arg : params) { String argName = arg.getName(); switch (argName) { case "HMM Name": name = arg.getValue(); name = name.trim(); break; case "Use Reference Annotation": command += "--hand "; break; } } } if (forGroup && multiJob) { name = group.getName() + "_HMM"; } if (name == null || "".equals(name)) { if (af != null) { if (af.getTitle().length() < 15) { name = af.getTitle(); } } if (name == null || "".equals(name)) { name = "Alignment"; } } command += "-n " + name.replace(' ', '_') + SPACE; if (!alignment.isNucleotide()) { command += FORCEAMINO; // TODO check for rna } else { command += FORCEDNA; } command += hmmTemp.getAbsolutePath() + SPACE + stoTemp.getAbsolutePath() + SPACE; return runCommand(command); } /** * Imports the .hmm file produced by hmmbuild. * * @throws IOException * @throws InterruptedException */ private void importData() throws IOException, InterruptedException { HMMFile file = new HMMFile( new FileParse(hmmTemp.getAbsolutePath(), DataSourceType.FILE)); SequenceI[] seqs = file.getSeqsAsArray(); SequenceI seq = seqs[0]; seq.createDatasetSequence(); if (group != null) { seq.insertCharAt(0, group.getStartRes(), '-'); seq.insertCharAt(group.getEndRes() + 1, alignment.getWidth() - group.getEndRes() - 1, '-'); seq.updateHMMMapping(); SequenceI topSeq = group.getSequencesInOrder(alignment)[0]; int topIndex = alignment.findIndex(topSeq); alignment.insertSequenceAt(topIndex, seq); group.setSeqrep(seq); group.addSequence(seq, false); } else { alignment.insertSequenceAt(0, seq); } if (viewport != null) { viewport.alignmentChanged(viewport.getAlignPanel()); viewport.getAlignPanel().adjustAnnotationHeight(); viewport.updateSequenceIdColours(); if (viewport.getAlignPanel().alignFrame.getSelectedHMM() == null) { viewport.getAlignPanel().alignFrame.setSelectedHMMSequence(seq); } } hmmTemp.delete(); stoTemp.delete(); } /** * Runs hmmbuild, and waits for the results to be imported before continuing */ public void hmmbuildWaitTillComplete() { Thread loader = new Thread(this); loader.start(); while (loader.isAlive()) { try { Thread.sleep(500); } catch (Exception ex) { } } } }