From f054ba1d438d155f4dbc2f8cbcc43faece656288 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Wed, 21 Feb 2018 16:18:29 +0000 Subject: [PATCH] JAL-2629 simplifying method signatures in Hmmer command classes --- src/jalview/gui/AlignFrame.java | 10 +- src/jalview/hmmer/HMMAlignThread.java | 228 ++++++++------------ src/jalview/hmmer/HMMBuildThread.java | 356 ++++++++++++++------------------ src/jalview/hmmer/HMMERParamStore.java | 17 +- src/jalview/hmmer/HMMSearchThread.java | 242 +++++++++------------- src/jalview/hmmer/HmmerCommand.java | 146 ++++++------- test/jalview/hmmer/HMMERTest.java | 2 +- 7 files changed, 425 insertions(+), 576 deletions(-) diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 834f4c8..b218e7a 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -1057,7 +1057,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, args); if (params.showRunDialog()) { - new Thread(new HMMAlignThread(this, true, params.getJobParams())) + new Thread(new HMMAlignThread(this, params.getJobParams())) .start(); } alignPanel.repaint(); @@ -1077,7 +1077,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, args); if (params.showRunDialog()) { - new Thread(new HMMSearchThread(this, true, params.getJobParams())) + new Thread(new HMMSearchThread(this, params.getJobParams())) .start(); } alignPanel.repaint(); @@ -1101,8 +1101,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { return; } - new Thread(new HMMAlignThread(this, true, null)) - .start(); + new Thread(new HMMAlignThread(this, null)).start(); } @Override @@ -1112,8 +1111,7 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, { return; } - new Thread(new HMMSearchThread(this, true, null)) - .start(); + new Thread(new HMMSearchThread(this, null)).start(); } /** diff --git a/src/jalview/hmmer/HMMAlignThread.java b/src/jalview/hmmer/HMMAlignThread.java index fadbdb1..582dc06 100644 --- a/src/jalview/hmmer/HMMAlignThread.java +++ b/src/jalview/hmmer/HMMAlignThread.java @@ -1,8 +1,6 @@ package jalview.hmmer; import jalview.analysis.AlignmentSorter; -import jalview.analysis.SeqsetUtils; -import jalview.bin.Cache; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentI; import jalview.datamodel.AlignmentOrder; @@ -31,6 +29,8 @@ public class HMMAlignThread extends HmmerCommand implements Runnable { static final String HMMALIGN = "hmmalign"; + static final String ARG_TRIM = "--trim"; + /* * feature settings from view that job was associated with */ @@ -46,41 +46,23 @@ public class HMMAlignThread extends HmmerCommand implements Runnable HiddenMarkovModel hmm; - List args; - - boolean newFrame; - - long barID; - - File hmmTemp = null; - - File outTemp = null; - - File inputTemp = null; - - List allOrders; - SequenceI[][] allResults; /** - * Constructor for the HMMAlignThread. If create new frame is set to true, a - * new frame will be created. + * Constructor for the HMMAlignThread * * @param af - * @param createNewFrame + * @param args */ - public HMMAlignThread(AlignFrame af, boolean createNewFrame, - List args) + public HMMAlignThread(AlignFrame af, List args) { - this.af = af; + super(af, args); alignment = af.getViewport().getAlignment(); if (alignment.getDataset() != null) { dataset = alignment.getDataset(); } - newFrame = createNewFrame; featureSettings = af.getFeatureRenderer().getSettings(); - this.args = args; } /** @@ -92,147 +74,120 @@ public class HMMAlignThread extends HmmerCommand implements Runnable @Override public void run() { - hmm = af.getSelectedHMM(); - barID = System.currentTimeMillis(); + long msgId = System.currentTimeMillis(); af.setProgressBar(MessageManager.getString("status.running_hmmalign"), - barID); + msgId); prepareAlignment(); SequenceI[][] subAlignments = msa.getVisibleContigs('-'); - allOrders = new ArrayList<>(); + + List allOrders = new ArrayList<>(); allResults = new SequenceI[subAlignments.length][]; int job = 0; for (SequenceI[] seqs : subAlignments) { - uniquifySequences(seqs); + stashSequences(seqs); try { - createTemporaryFiles(); - } catch (IOException e2) - { - e2.printStackTrace(); - } - try - { - exportData(seqs, outTemp.getAbsoluteFile(), hmm, - hmmTemp.getAbsoluteFile(), null); - } catch (IOException e1) - { - e1.printStackTrace(); - } - try - { - boolean ran = runCommand(); + File modelFile = createTempFile("hmm", ".hmm"); + File alignmentFile = createTempFile("output", ".sto"); + File resultFile = createTempFile("input", ".sto"); + + exportStockholm(seqs, alignmentFile.getAbsoluteFile(), null); + exportHmm(hmm, modelFile.getAbsoluteFile()); + + boolean ran = runCommand(modelFile, alignmentFile, resultFile); if (!ran) { JvOptionPane.showInternalMessageDialog(af, MessageManager.getString("warn.hmmalign_failed")); return; } - } catch (IOException | InterruptedException e) - { - e.printStackTrace(); - } - try - { - importData(job); - } catch (IOException | InterruptedException e) + + SequenceI[] result = importData(resultFile, allOrders); + allResults[job] = result; + modelFile.delete(); + alignmentFile.delete(); + resultFile.delete(); + } catch (IOException e) { - // TODO Auto-generated catch block e.printStackTrace(); } job++; } - displayResults(newFrame); - - af.setProgressBar("", barID); - - } + displayResults(allOrders); - /** - * Creates temporary files for exporting and importing the data. - * - * @throws IOException - */ - private void createTemporaryFiles() throws IOException - { - if (hmmTemp == null) - { - hmmTemp = File.createTempFile("hmm", ".hmm"); - hmmTemp.deleteOnExit(); - } - if (outTemp == null) - { - outTemp = File.createTempFile("output", ".sto"); - outTemp.deleteOnExit(); - } - inputTemp = File.createTempFile("input", ".sto"); - inputTemp.deleteOnExit(); + af.setProgressBar("", msgId); } /** - * Executes the hmmalign command in the command line + * Executes the hmmalign command and returns true if successful, false if an + * error is detected * + * @param modelFile + * the HMM to align to + * @param alignmentFile + * the sequences to align + * @param resultFile + * the file to hold the results of alignment * @return * @throws IOException - * @throws InterruptedException */ - private boolean runCommand() throws IOException, InterruptedException + private boolean runCommand(File modelFile, File alignmentFile, + File resultFile) + throws IOException { - String binaryPath = getCommandRoot(HMMALIGN); - if (binaryPath == null) { - return false; - } - String command = binaryPath + SPACE; - // todo parse version from ./hmmerbuild -h - String version = Cache.getProperty("HMMER_VERSION"); - if (!"3.1b2".equals(version)) + String command = getCommandPath(HMMALIGN); + if (command == null) { - // command += ALLCOL; // todo obsolete option? + return false; } - if (args != null) + List args = new ArrayList<>(); + args.add(command); + + if (params != null) { - for (ArgumentI arg : args) + for (ArgumentI arg : params) { String name = arg.getName(); - switch (name) + if (MessageManager.getString("label.trim_termini").equals(name)) { - case "Trim Non-Matching Termini": - command += "--trim"; + args.add(ARG_TRIM); } } } - command += " -o " + inputTemp.getAbsolutePath() + SPACE - + hmmTemp.getAbsolutePath() + SPACE - + outTemp.getAbsolutePath(); - return runCommand(command); + args.add("-o"); + args.add(resultFile.getAbsolutePath()); + args.add(modelFile.getAbsolutePath()); + args.add(alignmentFile.getAbsolutePath()); + + return runCommand(args); } /** - * Imports the data from the temporary file to which the output of hmmalign is - * directed. this is used for an internal job. + * Imports the data from the file holding the output of hmmalign + * + * @param resultFile + * @param allOrders + * a list of alignment orders to add to * - * @param index - * The index of the 'job' (or region of an alignment). + * @return * @throws IOException - * @throws InterruptedException */ - private void importData(int index) - throws IOException, InterruptedException + private SequenceI[] importData(File resultFile, + List allOrders) throws IOException { - StockholmFile file = new StockholmFile(inputTemp.getAbsolutePath(), + StockholmFile file = new StockholmFile(resultFile.getAbsolutePath(), DataSourceType.FILE); SequenceI[] result = file.getSeqsAsArray(); AlignmentOrder msaorder = new AlignmentOrder(result); AlignmentSorter.recoverOrder(result); - SeqsetUtils.deuniquify(hash, result); + recoverSequences(result); allOrders.add(msaorder); - allResults[index] = result; - hmmTemp.delete(); - outTemp.delete(); - inputTemp.delete(); + + return result; } /** @@ -240,59 +195,52 @@ public class HMMAlignThread extends HmmerCommand implements Runnable */ private void prepareAlignment() { - // hmmSeqs = alignment.getHMMConsensusSequences(true); msa = af.gatherSequencesForAlignment(); } /** - * Displays the results of all 'jobs'. + * Displays the results of all 'jobs' in a new frame * - * @param newFrame + * @param allOrders */ - private void displayResults(boolean newFrame) + private void displayResults(List allOrders) { AlignmentOrder[] arrOrders = allOrders .toArray(new AlignmentOrder[allOrders.size()]); Object[] newview = msa.getUpdatedView(allResults, arrOrders, '-'); - SequenceI[] alignment = (SequenceI[]) newview[0]; + SequenceI[] seqs = (SequenceI[]) newview[0]; HiddenColumns hidden = (HiddenColumns) newview[1]; - Alignment al = new Alignment(alignment); + Alignment al = new Alignment(seqs); al.setProperty("Alignment Program", "hmmalign"); if (dataset != null) { al.setDataset(dataset); } - if (newFrame) - { - displayInNewFrame(al, allOrders, hidden); - } + displayInNewFrame(al, allOrders, hidden); } /** - * Displays the results in a new frame. + * Displays the results in a new frame * * @param al - * The alignment containing the results. + * The alignment containing the results * @param alorders * The order of the sequences in the alignment on which the jobs were - * run. + * run * @param hidden - * Hidden columns in the previous alignment. + * Hidden columns in the previous alignment */ private void displayInNewFrame(AlignmentI al, List alorders, HiddenColumns hidden) { - AlignFrame af = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH, + AlignFrame alignFrame = new AlignFrame(al, hidden, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); // initialise with same renderer settings as in parent alignframe. - af.getFeatureRenderer().transferSettings(this.featureSettings); + alignFrame.getFeatureRenderer().transferSettings(this.featureSettings); - if (allOrders.size() > 0) - { - addSortByMenuItems(af, allOrders); - } + addSortByMenuItems(alignFrame, alorders); // TODO: refactor retrieve and show as new splitFrame as Desktop method @@ -319,14 +267,14 @@ public class HMMAlignThread extends HmmerCommand implements Runnable copyComplement.alignAs(al); if (copyComplement.getHeight() > 0) { - af.setTitle(this.af.getTitle()); + alignFrame.setTitle(this.af.getTitle()); AlignFrame af2 = new AlignFrame(copyComplement, AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); af2.setTitle(complementTitle); String linkedTitle = MessageManager .getString("label.linked_view_title"); JInternalFrame splitFrame = new SplitFrame( - al.isNucleotide() ? af : af2, al.isNucleotide() ? af2 : af); + al.isNucleotide() ? alignFrame : af2, al.isNucleotide() ? af2 : alignFrame); Desktop.addInternalFrame(splitFrame, linkedTitle, -1, -1); return; } @@ -335,23 +283,23 @@ public class HMMAlignThread extends HmmerCommand implements Runnable /* * Not from SplitFrame, or failed to created a complementary alignment */ - Desktop.addInternalFrame(af, af.getTitle(), AlignFrame.DEFAULT_WIDTH, + Desktop.addInternalFrame(alignFrame, alignFrame.getTitle(), AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT); } /** - * Add sort order options to the AlignFrame menus. + * Adds sort order options to the AlignFrame menus * - * @param af + * @param alignFrame * @param alorders */ - protected void addSortByMenuItems(AlignFrame af, + protected void addSortByMenuItems(AlignFrame alignFrame, List alorders) { // update orders if (alorders.size() == 1) { - af.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0)); + alignFrame.addSortByOrderMenuItem("hmmalign" + " Ordering", alorders.get(0)); } else { @@ -387,7 +335,7 @@ public class HMMAlignThread extends HmmerCommand implements Runnable } for (int i = 0, l = alorders.size(); i < l; i++) { - af.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering", + alignFrame.addSortByOrderMenuItem("hmmalign" + (names.get(i)) + " Ordering", alorders.get(i)); } } diff --git a/src/jalview/hmmer/HMMBuildThread.java b/src/jalview/hmmer/HMMBuildThread.java index 24106d6..e7bc58c 100644 --- a/src/jalview/hmmer/HMMBuildThread.java +++ b/src/jalview/hmmer/HMMBuildThread.java @@ -1,6 +1,6 @@ package jalview.hmmer; -import jalview.analysis.SeqsetUtils; +import jalview.api.AlignViewportI; import jalview.datamodel.AlignmentI; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceGroup; @@ -15,7 +15,6 @@ 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; @@ -24,275 +23,231 @@ import javax.swing.JOptionPane; public class HMMBuildThread extends HmmerCommand implements Runnable { - AlignViewport viewport; + static final String ARG_AMINO = "--amino"; - boolean multiJob = false; + static final String ARG_DNA = "--dna"; - AlignmentI alignment; - - SequenceGroup group; - - List params; - - boolean forGroup = false; - - File hmmTemp = null; - - File stoTemp = null; + static final String ARG_RNA = "--rna"; - long barID; + AlignmentI alignment; /** - * This is used for validation purposes. Do not use! + * Constructor * - * @param viewport + * @param alignFrame + * @param args */ - public HMMBuildThread(AlignmentI alignment) - { - this.alignment = alignment; - forGroup = false; - } - - public HMMBuildThread(AlignFrame af, List args) + public HMMBuildThread(AlignFrame alignFrame, List args) { - this.af = af; - viewport = af.getViewport(); - params = args; + super(alignFrame, args); } /** - * Builds a HMM from an alignment, then imports and adds it to the alignment. + * Builds a HMM from an alignment (and/or groups), then imports and adds it to + * the alignment (and/or groups) */ @Override public void run() { - barID = System.currentTimeMillis(); + long msgID = System.currentTimeMillis(); if (af != null) { af.setProgressBar(MessageManager.getString("status.running_hmmbuild"), - barID); + msgID); } - List groups = new ArrayList<>(); - if (params != null) + AlignViewportI viewport = af.getViewport(); + try { - for (ArgumentI arg : params) + List groups = new ArrayList<>(); + if (params != null) { - String name = arg.getName(); - if (MessageManager.getString("label.hmmbuild_for").equals(name)) + for (ArgumentI arg : params) { - String value = arg.getValue(); - if ("Alignment".equals(value)) - { - alignment = viewport.getAlignment(); - break; - } - else if ("All groups and alignment".equals(value)) + String name = arg.getName(); + if (MessageManager.getString("label.hmmbuild_for").equals(name)) { - alignment = viewport.getAlignment(); - groups.addAll(viewport.getAlignment().getGroups()); - if (groups.size() > 0) + String value = arg.getValue(); + if (MessageManager.getString("label.alignment").equals(value)) { - multiJob = true; + alignment = viewport.getAlignment(); } - break; - } - else if ("All groups".equals(value)) - { - alignment = null; - groups = viewport.getAlignment().getGroups(); - if (groups.size() > 0) + else if (MessageManager.getString("label.groups_and_alignment") + .equals(value)) { - multiJob = true; + alignment = viewport.getAlignment(); + groups.addAll(viewport.getAlignment().getGroups()); + } + else if (MessageManager.getString("label.groups").equals(value)) + { + alignment = null; + groups = viewport.getAlignment().getGroups(); + } + else if ("label.selected_group".equals(value)) + { + alignment = null; + groups.add(viewport.getSelectionGroup()); } - 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()) + else if (MessageManager.getString("label.use_reference") + .equals(name)) { - if (af != null) + // todo disable this option if no RF annotation on alignment + if (!af.getViewport().hasReferenceAnnotation()) { - af.setProgressBar( - MessageManager.getString("status.running_hmmbuild"), - barID); + JvOptionPane.showInternalMessageDialog(af, MessageManager + .getString("warn.no_reference_annotation")); + // return; } - JvOptionPane.showInternalMessageDialog(af, MessageManager - .getString("warn.no_reference_annotation")); - return; } } } - } - else if (viewport != null) - { - alignment = viewport.getAlignment(); - } + else if (viewport != null) + { + alignment = viewport.getAlignment(); + } - if (alignment != null) - { - forGroup = false; - runHMMBuild(); - } + if (alignment != null) + { + runHMMBuild(null); + } - if (alignment == null) - { - alignment = viewport.getAlignment(); - } + if (alignment == null) + { + alignment = viewport.getAlignment(); + } - if (groups != null && groups.size() > 0) - { for (SequenceGroup grp : groups) { - group = grp; - forGroup = true; - runHMMBuild(); + runHMMBuild(grp); } - } - - if (af != null) + } finally { - af.setProgressBar("", barID); + if (af != null) + { + af.setProgressBar("", msgID); + } } } - private void runHMMBuild() + /** + * Runs hmmbuild on the alignment, or on the group if one is specified + * + * @param grp + */ + private void runHMMBuild(SequenceGroup group) { if (alignment == null && group == null) { JOptionPane.showMessageDialog(af, MessageManager.getString("warn.no_sequence_data")); } + File hmmFile = null; + File alignmentFile = null; try { - hmmTemp = File.createTempFile("hmm", ".hmm"); - hmmTemp.deleteOnExit(); - stoTemp = File.createTempFile("output", ".sto"); - stoTemp.deleteOnExit(); - } catch (IOException e1) - { - e1.printStackTrace(); - } - - try - { - try + hmmFile = createTempFile("hmm", ".hmm"); + alignmentFile = createTempFile("output", ".sto"); + SequenceI[] array; + List hmmSeqs = null; + if (group != null) { - 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) + hmmSeqs = group.getHMMConsensusSequences(); + array = group.getSelectionAsNewSequences(alignment); + } + else + { + hmmSeqs = alignment.getHMMConsensusSequences(); + // todo pad gaps in an unaligned SequenceGroup as well? + if (!alignment.isAligned()) { - if (af != null) - { - JOptionPane.showMessageDialog(af, - MessageManager.getString("warn.no_sequence_data")); - } - return; + alignment.padGaps(); } + array = alignment.getSequencesArray(); + } - /* - * copy over sequences excluding hmm consensus sequences - */ - SequenceI[] newArr = new SequenceI[array.length - hmmSeqs.size()]; - int index = 0; - for (SequenceI seq : array) + if (array.length < 1) + { + if (af != null) { - if (!seq.isHMMConsensusSequence()) - { - newArr[index] = new Sequence(seq); - index++; - } + JOptionPane.showMessageDialog(af, + MessageManager.getString("warn.no_sequence_data")); } + return; + } - uniquifySequences(newArr); - - if (forGroup) + /* + * 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()) { - exportData(newArr, stoTemp, null, null, group); + alignment.deleteSequence(seq); } else { - exportData(newArr, stoTemp, null, null, alignment); + newArr[index] = new Sequence(seq); + index++; } + } - SeqsetUtils.deuniquify(hash, array); + stashSequences(newArr); - } catch (FileNotFoundException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); + exportStockholm(newArr, alignmentFile, + group != null ? group : alignment); - } - try - { - boolean ran = runCommand(); - if (!ran) - { - return; - } - } catch (IOException | InterruptedException e) - { - // TODO Auto-generated catch block - e.printStackTrace(); - } - try - { + recoverSequences(array); - importData(); - } catch (IOException | InterruptedException e) + boolean ran = runCommand(alignmentFile, hmmFile, group); + if (!ran) { - // TODO Auto-generated catch block - e.printStackTrace(); + return; } + importData(hmmFile, group); } catch (Exception e) { e.printStackTrace(); + } finally + { + if (hmmFile != null) + { + hmmFile.delete(); + } + if (alignmentFile != null) + { + alignmentFile.delete(); + } } } /** - * Executes the hmmbuild command in the command line. + * Constructs and executes the hmmbuild command as a separate process + * + * @param sequences + * the alignment from which the HMM is built + * @param hmm + * the output file to which the HMM is written + * @param group + * (optional) group for which the hmm is generated * * @return * @throws IOException * @throws InterruptedException */ - private boolean runCommand() throws IOException, InterruptedException + private boolean runCommand(File sequences, File hmm, SequenceGroup group) + throws IOException, InterruptedException { - String binaryPath = getCommandRoot(HMMBUILD); - if (binaryPath == null) + + String cmd = getCommandPath(HMMBUILD); + if (cmd == null) { return false; } - String command = binaryPath + SPACE; + List args = new ArrayList<>(); + args.add(cmd); String name = null; if (params != null) @@ -307,14 +262,13 @@ public class HMMBuildThread extends HmmerCommand implements Runnable name = name.trim(); break; case "Use Reference Annotation": - command += "--hand "; + args.add("--hand"); break; - } } } - if (forGroup && multiJob) + if (group != null) { name = group.getName() + "_HMM"; } @@ -335,31 +289,38 @@ public class HMMBuildThread extends HmmerCommand implements Runnable } - command += "-n " + name.replace(' ', '_') + SPACE; + args.add("-n"); + args.add(name.replace(' ', '_')); if (!alignment.isNucleotide()) { - command += FORCEAMINO; // TODO check for rna + args.add(ARG_AMINO); // TODO check for rna } else { - command += FORCEDNA; + args.add(ARG_DNA); } - command += hmmTemp.getAbsolutePath() + SPACE + stoTemp.getAbsolutePath() - + SPACE; - return runCommand(command); + args.add(hmm.getAbsolutePath()); + args.add(sequences.getAbsolutePath()); + + return runCommand(args); } /** - * Imports the .hmm file produced by hmmbuild. + * Imports the .hmm file produced by hmmbuild, and inserts the HMM consensus + * sequence (with attached HMM profile) as the first sequence in the alignment + * or group for which it was generated * + * @param hmmFile + * @oparam group (optional) the group for which the hmm was generated * @throws IOException * @throws InterruptedException */ - private void importData() throws IOException, InterruptedException + private void importData(File hmmFile, SequenceGroup group) + throws IOException, InterruptedException { HMMFile file = new HMMFile( - new FileParse(hmmTemp.getAbsolutePath(), DataSourceType.FILE)); + new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE)); SequenceI[] seqs = file.getSeqsAsArray(); SequenceI seq = seqs[0]; seq.createDatasetSequence(); @@ -380,6 +341,7 @@ public class HMMBuildThread extends HmmerCommand implements Runnable alignment.insertSequenceAt(0, seq); } + AlignViewport viewport = af.getViewport(); if (viewport != null) { viewport.alignmentChanged(viewport.getAlignPanel()); @@ -391,8 +353,6 @@ public class HMMBuildThread extends HmmerCommand implements Runnable viewport.getAlignPanel().alignFrame.setSelectedHMMSequence(seq); } } - hmmTemp.delete(); - stoTemp.delete(); } /** diff --git a/src/jalview/hmmer/HMMERParamStore.java b/src/jalview/hmmer/HMMERParamStore.java index af55dab..17f582e 100644 --- a/src/jalview/hmmer/HMMERParamStore.java +++ b/src/jalview/hmmer/HMMERParamStore.java @@ -20,27 +20,24 @@ import java.util.Scanner; public class HMMERParamStore implements ParamDatastoreI { - String name; List presets = new ArrayList<>(); - public HMMERParamStore(String name) + public HMMERParamStore(String nam) { - this.name = name; + this.name = nam; } @Override public List getPresets() { - // TODO Auto-generated method stub return presets; } @Override - public WsParamSetI getPreset(String name) + public WsParamSetI getPreset(String nam) { - // TODO Auto-generated method stub return null; } @@ -148,6 +145,7 @@ public class HMMERParamStore implements ParamDatastoreI { args.add(new StringParameter(MessageManager.getString("label.hmm_name"), MessageManager.getString("label.hmm_name_desc"), true, "")); + // todo only enable Use Reference Annotation if RF is present args.add(new BooleanOption( MessageManager.getString("label.use_reference"), MessageManager.getString("label.use_reference_desc"), true, @@ -168,15 +166,12 @@ public class HMMERParamStore implements ParamDatastoreI @Override public boolean presetExists(String name) { - // TODO Auto-generated method stub return false; } @Override public void deletePreset(String name) { - // TODO Auto-generated method stub - } @Override @@ -191,8 +186,6 @@ public class HMMERParamStore implements ParamDatastoreI public void updatePreset(String oldName, String presetName, String text, List jobParams) { - // TODO Auto-generated method stub - } @Override @@ -200,7 +193,6 @@ public class HMMERParamStore implements ParamDatastoreI String description, String[] serviceURL, String parameters) throws IOException { - // TODO Auto-generated method stub return null; } @@ -208,7 +200,6 @@ public class HMMERParamStore implements ParamDatastoreI public String generateServiceParameterFile(WsParamSetI pset) throws IOException { - // TODO Auto-generated method stub return null; } diff --git a/src/jalview/hmmer/HMMSearchThread.java b/src/jalview/hmmer/HMMSearchThread.java index d3f8968..d974b49 100644 --- a/src/jalview/hmmer/HMMSearchThread.java +++ b/src/jalview/hmmer/HMMSearchThread.java @@ -12,7 +12,6 @@ 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; @@ -31,190 +30,154 @@ public class HMMSearchThread extends HmmerCommand implements Runnable { static final String HMMSEARCH = "hmmsearch"; - /* - * feature settings from view that job was associated with - */ - protected FeatureRendererSettings featureSettings = null; - - HiddenMarkovModel hmm; - - boolean newFrame; - boolean realign = false; boolean trim = false; - Integer numberOfSequences = null; - - long barID; - - List params; - - File hmmTemp = null; - - File inputAlignmentTemp = null; - - File inputTableTemp = null; - - File databaseFile = null; + int seqsToReturn = Integer.MAX_VALUE; SequenceI[] seqs; /** - * Constructor for the HMMSearchThread. If create new frame is set to true, a - * new frame will be created. + * Constructor for the HMMSearchThread * * @param af - * @param createNewFrame */ - public HMMSearchThread(AlignFrame af, boolean createNewFrame, - List args) + public HMMSearchThread(AlignFrame af, List args) { - this.af = af; - newFrame = createNewFrame; - featureSettings = af.getFeatureRenderer().getSettings(); - params = 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 (if true). + * imported and displayed in a new frame */ @Override public void run() { - if (af.getSelectedHMM() == null) + HiddenMarkovModel hmm = af.getSelectedHMM(); + if (hmm == null) { JOptionPane.showMessageDialog(af, MessageManager.getString("warn.no_selected_hmm")); return; } - else - { - hmm = af.getSelectedHMM(); - } SequenceI hmmSeq = af.getSelectedHMMSequence(); - barID = System.currentTimeMillis(); + long msgId = System.currentTimeMillis(); af.setProgressBar(MessageManager.getString("status.running_hmmsearch"), - barID); + msgId); try { - createTemporaryFiles(); - } catch (IOException e2) - { - e2.printStackTrace(); - } - try - { - exportData(null, null, hmm, hmmTemp.getAbsoluteFile(), null); - } catch (IOException e1) - { - e1.printStackTrace(); - } - try - { - boolean ran = runCommand(); + 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(); } - try - { - importData(hmmSeq); - } catch (IOException | InterruptedException e) + finally { - // TODO Auto-generated catch block - e.printStackTrace(); + af.setProgressBar("", msgId); } - - af.setProgressBar("", barID); - } /** - * Creates temporary files for exporting and importing the data. + * 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. * - * @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. + * @param searchOutputFile + * @param hitsAlignmentFile + * @param hmmFile * * @return * @throws IOException - * @throws InterruptedException */ - private boolean runCommand() throws IOException, InterruptedException + private boolean runCommand(File searchOutputFile, File hitsAlignmentFile, + File hmmFile) throws IOException { - String binaryPath = getCommandRoot(HMMSEARCH); - if (binaryPath == null) + String command = getCommandPath(HMMSEARCH); + if (command == null) { return false; } - String command = binaryPath + " -o " - + inputTableTemp.getAbsolutePath() + " -A " - + inputAlignmentTemp.getAbsolutePath() + SPACE; + 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(); - switch (name) + 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)) { - 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() + SPACE; - break; - case "Sequence Score Threshold": - command += "-incT " + arg.getValue() + SPACE; - break; - case "Domain E-value Threshold": - command += "--incdomE " + arg.getValue() + SPACE; - break; - case "Domain Score Threshold": - command += "--incdomT " + arg.getValue() + SPACE; - break; - case "Trim Non-Matching Termini": trim = true; - break; - case "Database": + } + else if (MessageManager.getString("label.database").equals(name)) + { dbFound = true; dbPath = arg.getValue(); if (!MessageManager.getString("label.this_alignment") @@ -223,7 +186,6 @@ public class HMMSearchThread extends HmmerCommand implements Runnable databaseFile = new File(dbPath); } } - } } @@ -240,16 +202,16 @@ public class HMMSearchThread extends HmmerCommand implements Runnable StockholmFile stoFile = new StockholmFile(copy); stoFile.setSeqs(copy.getSequencesArray()); String alignmentString = stoFile.print(); - databaseFile = File.createTempFile("database", ".sto"); - databaseFile.deleteOnExit(); + databaseFile = createTempFile("database", ".sto"); PrintWriter writer = new PrintWriter(databaseFile); writer.print(alignmentString); writer.close(); } - command += hmmTemp.getAbsolutePath() + SPACE - + databaseFile.getAbsolutePath(); - return runCommand(command); + args.add(hmmFile.getAbsolutePath()); + args.add(databaseFile.getAbsolutePath()); + + return runCommand(args); } /** @@ -258,7 +220,8 @@ public class HMMSearchThread extends HmmerCommand implements Runnable * * @param hmmSeq */ - private void importData(SequenceI hmmSeq) + private void importData(SequenceI hmmSeq, File inputAlignmentTemp, + File hmmTemp, File searchOutputFile) throws IOException, InterruptedException { BufferedReader br = new BufferedReader( @@ -275,27 +238,12 @@ public class HMMSearchThread extends HmmerCommand implements Runnable inputAlignmentTemp.getAbsolutePath(), DataSourceType.FILE)); seqs = file.getSeqsAsArray(); - readTable(); + readTable(searchOutputFile); - SequenceI[] hmmAndSeqs; - if (numberOfSequences != null && numberOfSequences < seqs.length) - { - hmmAndSeqs = new SequenceI[numberOfSequences + 1]; - } - else - { - hmmAndSeqs = new SequenceI[seqs.length + 1]; - } + int seqCount = Math.min(seqs.length, seqsToReturn); + SequenceI[] hmmAndSeqs = new SequenceI[seqCount + 1]; 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); - } + System.arraycopy(seqs, 0, hmmAndSeqs, 1, seqCount); AlignmentI alignment = new Alignment(hmmAndSeqs); AlignFrame frame = new AlignFrame(alignment, 1, 1); @@ -308,12 +256,12 @@ public class HMMSearchThread extends HmmerCommand implements Runnable MessageManager.getString("label.trim_termini_desc"), true, true, true, null)); } - HMMAlignThread hmmalign = new HMMAlignThread(frame, true, alignArgs); + HMMAlignThread hmmalign = new HMMAlignThread(frame, alignArgs); hmmalign.hmmalignWaitTillComplete(); frame = null; hmmTemp.delete(); inputAlignmentTemp.delete(); - inputTableTemp.delete(); + searchOutputFile.delete(); } finally { if (br != null) @@ -343,7 +291,7 @@ public class HMMSearchThread extends HmmerCommand implements Runnable } - void readTable() throws IOException + void readTable(File inputTableTemp) throws IOException { BufferedReader br = new BufferedReader(new FileReader(inputTableTemp)); String line = ""; diff --git a/src/jalview/hmmer/HmmerCommand.java b/src/jalview/hmmer/HmmerCommand.java index a9d7018..557598b 100644 --- a/src/jalview/hmmer/HmmerCommand.java +++ b/src/jalview/hmmer/HmmerCommand.java @@ -1,5 +1,6 @@ package jalview.hmmer; +import jalview.analysis.SeqsetUtils; import jalview.bin.Cache; import jalview.datamodel.Alignment; import jalview.datamodel.AlignmentAnnotation; @@ -14,6 +15,7 @@ import jalview.gui.Preferences; import jalview.io.HMMFile; import jalview.io.StockholmFile; import jalview.util.MessageManager; +import jalview.ws.params.ArgumentI; import java.io.BufferedReader; import java.io.File; @@ -33,28 +35,17 @@ public class HmmerCommand { public static final String HMMBUILD = "hmmbuild"; - public String JALVIEWDIRECTORY = System.getProperty("user.dir") - + File.separator; + private Hashtable hash = new Hashtable(); - public String OUTPUTALIGNMENT; - - public final String SPACE = " "; - - public final String ALLCOL = "--allcol "; - - public final String TRIM = "--trim "; - - public final String FORCEAMINO = "--amino "; - - public final String FORCEDNA = "--dna "; - - public final String FORCERNA = "--rna "; - - Hashtable hash = new Hashtable(); + protected AlignFrame af; - List hmmSeqs; + protected List params; - protected AlignFrame af; + public HmmerCommand(AlignFrame alignFrame, List args) + { + af = alignFrame; + params = args; + } public static boolean isHmmerAvailable() { @@ -64,39 +55,40 @@ public class HmmerCommand /** * Uniquifies the sequences when exporting and stores their details in a - * hashtable. + * hashtable * * @param seqs */ - public void uniquifySequences(SequenceI[] seqs) + protected void stashSequences(SequenceI[] seqs) { - hash = jalview.analysis.SeqsetUtils.uniquify(seqs, true); + hash = SeqsetUtils.uniquify(seqs, true); } /** - * Recover the sequence data lost by uniquifying. + * Restores the sequence data lost by uniquifying * * @param seqs */ - public void recoverSequenceNames(SequenceI[] seqs) + protected void recoverSequences(SequenceI[] seqs) { - jalview.analysis.SeqsetUtils.deuniquify(hash, seqs); + SeqsetUtils.deuniquify(hash, seqs); } /** - * Runs a command in the command line. + * Runs a command as a separate process * * @param command + * the executable command and any arguments to it * @throws IOException - * @throws InterruptedException */ - public boolean runCommand(String command) - throws IOException, InterruptedException + public boolean runCommand(List command) + throws IOException { try { - final Process p = Runtime.getRuntime().exec(command); - + ProcessBuilder pb = new ProcessBuilder(command); + pb.redirectErrorStream(true); // send syserr to sysout + final Process p = pb.start(); new Thread(new Runnable() { @Override @@ -104,13 +96,13 @@ public class HmmerCommand { BufferedReader input = new BufferedReader( new InputStreamReader(p.getInputStream())); - String line = null; - try { - while ((line = input.readLine()) != null) + String line = input.readLine(); + while (line != null) { System.out.println(line); + line = input.readLine(); } } catch (IOException e) { @@ -120,30 +112,33 @@ public class HmmerCommand }).start(); p.waitFor(); + return p.exitValue() == 0; // 0 is success, by convention } catch (Exception e) { e.printStackTrace(); return false; } - return true; } /** - * Exports an alignment and/or HMM to the specified file. + * Exports an alignment (and possibly annotation) to the specified file, in + * Stockholm format * - * @param alignment + * @param seqs + * @param toFile + * @param annotated * @throws IOException */ - public void exportData(SequenceI[] seqs, File stoLocation, - HiddenMarkovModel hmm, File hmmLocation, AnnotatedCollectionI al) + public void exportStockholm(SequenceI[] seqs, File toFile, + AnnotatedCollectionI annotated) throws IOException { if (seqs != null) { AlignmentI newAl = new Alignment(seqs); - if (stoLocation != null && al != null) + if (toFile != null && annotated != null) { - for (AlignmentAnnotation annot : al.getAlignmentAnnotation()) + for (AlignmentAnnotation annot : annotated.getAlignmentAnnotation()) { if (annot.label.contains("Reference") || "RF".equals(annot.label)) { @@ -167,38 +162,10 @@ public class HmmerCommand StockholmFile file = new StockholmFile(newAl); String output = file.print(seqs, false); - PrintWriter writer = new PrintWriter(stoLocation); + PrintWriter writer = new PrintWriter(toFile); writer.println(output); writer.close(); } - - if (hmm != null) - { - HMMFile file = new HMMFile(hmm); - PrintWriter writer = new PrintWriter(hmmLocation); - writer.print(file.print()); - writer.close(); - } - } - - /** - * Returns the list of HMM sequences removed - * - * @return - */ - public List getHmmSeqs() - { - return hmmSeqs; - } - - /** - * Sets the list of removed HMM sequences - * - * @param hmmSeqs - */ - public void setHmmSeqs(List hmmSeqs) - { - this.hmmSeqs = hmmSeqs; } /** @@ -209,7 +176,7 @@ public class HmmerCommand * command short name e.g. hmmalign * @return */ - protected String getCommandRoot(String cmd) + protected String getCommandPath(String cmd) { String binariesFolder = Cache.getProperty(Preferences.HMMER_PATH); File file = getExecutable(cmd, binariesFolder); @@ -248,4 +215,41 @@ public class HmmerCommand } return file; } + + /** + * A convenience method to create a temporary file that is deleted on exit of + * the JVM + * + * @param prefix + * @param suffix + * @return + * @throws IOException + */ + protected File createTempFile(String prefix, String suffix) + throws IOException + { + File f = File.createTempFile(prefix, suffix); + f.deleteOnExit(); + return f; + + } + + /** + * Exports an HMM to the specified file + * + * @param hmm + * @param hmmFile + * @throws IOException + */ + public void exportHmm(HiddenMarkovModel hmm, File hmmFile) + throws IOException + { + if (hmm != null) + { + HMMFile file = new HMMFile(hmm); + PrintWriter writer = new PrintWriter(hmmFile); + writer.print(file.print()); + writer.close(); + } + } } diff --git a/test/jalview/hmmer/HMMERTest.java b/test/jalview/hmmer/HMMERTest.java index c922133..da6140b 100644 --- a/test/jalview/hmmer/HMMERTest.java +++ b/test/jalview/hmmer/HMMERTest.java @@ -84,7 +84,7 @@ public class HMMERTest { @Test(priority = 1) public void testHMMAlign() throws MalformedURLException, IOException { - HMMAlignThread thread = new HMMAlignThread(frame, true, + HMMAlignThread thread = new HMMAlignThread(frame, new ArrayList()); try { -- 1.7.10.2