Merge branch 'features/mchmmer' of https://source.jalview.org/git/jalview.git into...
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 17 Apr 2018 17:44:41 +0000 (18:44 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 17 Apr 2018 17:44:41 +0000 (18:44 +0100)
Conflicts:
src/jalview/hmmer/HmmerCommand.java

1  2 
.classpath
src/jalview/hmmer/HMMAlign.java
src/jalview/hmmer/HMMBuild.java
src/jalview/hmmer/HMMSearch.java
src/jalview/hmmer/HmmerCommand.java

diff --combined .classpath
@@@ -66,7 -66,7 +66,7 @@@
        <classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
        <classpathentry kind="lib" path="lib/biojava-core-4.1.0.jar"/>
        <classpathentry kind="lib" path="lib/biojava-ontology-4.1.0.jar"/>
--      <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
++      <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="lib" path="lib/htsjdk-2.12.0.jar"/>
        <classpathentry kind="lib" path="lib/groovy-all-2.4.12-indy.jar"/>
        <classpathentry kind="output" path="classes"/>
@@@ -64,7 -64,12 +64,7 @@@ public class HMMAlign extends HmmerComm
    @Override
    public void run()
    {
 -    HiddenMarkovModel hmm = af.getSelectedHMM();
 -    if (hmm == null)
 -    {
 -      System.err.println("Can't run hmmalign as no HMM profile selected");
 -      return;
 -    }
 +    HiddenMarkovModel hmm = getHmmProfile();
  
      long msgId = System.currentTimeMillis();
      af.setProgressBar(MessageManager.getString("status.running_hmmalign"),
@@@ -92,8 -97,8 +92,8 @@@
          boolean ran = runCommand(modelFile, alignmentFile, resultFile);
          if (!ran)
          {
 -          JvOptionPane.showInternalMessageDialog(af,
 -                  MessageManager.getString("warn.hmmalign_failed"));
 +          JvOptionPane.showInternalMessageDialog(af, MessageManager
 +                  .formatMessage("warn.command_failed", "hmmalign"));
            return;
          }
  
        }
      }
      args.add("-o");
-     args.add(resultFile.getAbsolutePath());
-     args.add(modelFile.getAbsolutePath());
-     args.add(alignmentFile.getAbsolutePath());
+     args.add(getFilePath(resultFile));
+     args.add(getFilePath(modelFile));
+     args.add(getFilePath(alignmentFile));
      
      return runCommand(args);
    }
    private SequenceI[] importData(File resultFile,
            List<AlignmentOrder> allOrders) throws IOException
    {
-     StockholmFile file = new StockholmFile(resultFile.getAbsolutePath(),
+     StockholmFile file = new StockholmFile(getFilePath(resultFile),
              DataSourceType.FILE);
      SequenceI[] result = file.getSeqsAsArray();
      AlignmentOrder msaorder = new AlignmentOrder(result);
        al.setDataset(dataset);
      }
  
 -    /*
 -     * hack to ensure hmm set on alignment
 -     */
 -    if (al.getSequenceAt(0).hasHMMProfile())
 -    {
 -      al.setHmmConsensus(al.getSequenceAt(0));
 -    }
 -
      displayInNewFrame(al, allOrders, hidden, title);
    }
  
@@@ -188,8 -188,6 +188,8 @@@ public class HMMBuild extends HmmerComm
        boolean ran = runCommand(alignmentFile, hmmFile, ac);
        if (!ran)
        {
 +        JvOptionPane.showInternalMessageDialog(af, MessageManager
 +                .formatMessage("warn.command_failed", "hmmbuild"));
          return;
        }
        importData(hmmFile, ac);
     */
    void deleteHmmSequences(AnnotatedCollectionI ac)
    {
 -    SequenceI hmmSeq = ac.getHmmConsensus();
 -    if (hmmSeq != null)
 +    List<SequenceI> hmmSeqs = ac.getHmmSequences();
 +    for (SequenceI hmmSeq : hmmSeqs)
      {
        if (ac instanceof SequenceGroup)
        {
        args.add(ARG_DNA);
      }
  
-     args.add(hmmFile.getAbsolutePath());
-     args.add(sequencesFile.getAbsolutePath());
+     args.add(getFilePath(hmmFile));
+     args.add(getFilePath(sequencesFile));
  
      return runCommand(args);
    }
        alignment.insertSequenceAt(topIndex, hmmSeq);
        ac.setSeqrep(hmmSeq);
        grp.addSequence(hmmSeq, false);
 -      grp.setHmmConsensus(hmmSeq);
      }
      else
      {
        alignment.insertSequenceAt(0, hmmSeq);
 -      alignment.setHmmConsensus(hmmSeq);
 -    }
 -
 -    if (af.getSelectedHMM() == null)
 -    {
 -      af.setSelectedHMMSequence(hmmSeq);
      }
    }
  }
@@@ -1,6 -1,5 +1,6 @@@
  package jalview.hmmer;
  
 +import jalview.bin.Cache;
  import jalview.datamodel.Alignment;
  import jalview.datamodel.AlignmentAnnotation;
  import jalview.datamodel.AlignmentI;
@@@ -16,14 -15,12 +16,14 @@@ import jalview.util.FileUtils
  import jalview.util.MessageManager;
  import jalview.ws.params.ArgumentI;
  import jalview.ws.params.simple.BooleanOption;
 +import jalview.ws.params.simple.Option;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileReader;
  import java.io.IOException;
  import java.util.ArrayList;
 +import java.util.Collections;
  import java.util.List;
  import java.util.Scanner;
  
@@@ -31,8 -28,6 +31,8 @@@ import javax.swing.JOptionPane
  
  public class HMMSearch extends HmmerCommand
  {
 +  private static final String PARAMNAME_NO_OF_RESULTS = MessageManager.getString("label.number_of_results");
 +
    static final String HMMSEARCH = "hmmsearch";
  
    boolean realign = false;
    @Override
    public void run()
    {
 -    HiddenMarkovModel hmm = af.getSelectedHMM();
 +    HiddenMarkovModel hmm = getHmmProfile();
      if (hmm == null)
      {
 -      JOptionPane.showMessageDialog(af,
 -              MessageManager.getString("warn.no_selected_hmm"));
 +      // shouldn't happen if we got this far
 +      Cache.log.error("Error: no hmm for hmmsearch");
        return;
      }
  
 -    SequenceI hmmSeq = af.getSelectedHMMSequence();
 +    SequenceI hmmSeq = hmm.getConsensusSequence();// af.getSelectedHMMSequence();
      long msgId = System.currentTimeMillis();
      af.setProgressBar(MessageManager.getString("status.running_hmmsearch"),
              msgId);
@@@ -88,8 -83,8 +88,8 @@@
        boolean ran = runCommand(searchOutputFile, hitsAlignmentFile, hmmFile);
        if (!ran)
        {
 -        JvOptionPane.showInternalMessageDialog(af,
 -                MessageManager.getString("warn.hmmsearch_failed"));
 +        JvOptionPane.showInternalMessageDialog(af, MessageManager
 +                .formatMessage("warn.command_failed", "hmmsearch"));
          return;
        }
  
      List<String> args = new ArrayList<>();
      args.add(command);
      args.add("-o");
-     args.add(searchOutputFile.getAbsolutePath());
+     args.add(getFilePath(searchOutputFile));
      args.add("-A");
-     args.add(hitsAlignmentFile.getAbsolutePath());
+     args.add(getFilePath(hitsAlignmentFile));
  
      boolean dbFound = false;
      String dbPath = "";
      {
        /*
         * no external database specified for search, so
 -       * export current alignment as 'database' to search
 +       * export current alignment as 'database' to search,
 +       * excluding any HMM consensus sequences it contains
         */
        databaseFile = FileUtils.createTempFile("database", ".sto");
        AlignmentI al = af.getViewport().getAlignment();
        AlignmentI copy = new Alignment(al);
 -      SequenceI hmms = copy.getHmmConsensus();
 -      if (hmms != null)
 +      List<SequenceI> hmms = copy.getHmmSequences();
 +      for (SequenceI hmmSeq : hmms)
        {
 -        copy.deleteSequence(hmms);
 +        copy.deleteSequence(hmmSeq);
        }
        exportStockholm(copy.getSequencesArray(), databaseFile, null);
        // StockholmFile stoFile = new StockholmFile(copy);
        // writer.close();
      }
  
-     args.add(hmmFile.getAbsolutePath());
-     args.add(databaseFile.getAbsolutePath());
+     args.add(getFilePath(hmmFile));
+     args.add(getFilePath(databaseFile));
  
      return runCommand(args);
    }
        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);
 +      /*
 +       * and align the search results to the HMM profile
 +       */
 +      AlignmentI al = new Alignment(hmmAndSeqs);
 +      AlignFrame frame = new AlignFrame(al, 1, 1);
        List<ArgumentI> alignArgs = new ArrayList<>();
 +      String defSeq = hmmSeq.getName();
 +      List<String> options = Collections.singletonList(defSeq);
 +      Option option = new Option(MessageManager.getString("label.use_hmm"),
 +              "", true, defSeq, defSeq, options, null);
 +      alignArgs.add(option);
        if (trim)
        {
          alignArgs.add(new BooleanOption(
@@@ -97,19 -97,19 +97,19 @@@ public abstract class HmmerCommand impl
     * Runs a command as a separate process and waits for it to complete. Answers
     * true if the process return status is zero, else false.
     * 
-    * @param command
+    * @param commands
     *          the executable command and any arguments to it
     * @throws IOException
     */
-   public boolean runCommand(List<String> command)
+   public boolean runCommand(List<String> commands)
            throws IOException
    {
-     List<String> commands = Platform.isWindows() ? wrapWithCygwin(command)
-             : command;
+     List<String> args = Platform.isWindows() ? wrapWithCygwin(commands)
+             : commands;
  
      try
      {
-       ProcessBuilder pb = new ProcessBuilder(commands);
+       ProcessBuilder pb = new ProcessBuilder(args);
        pb.redirectErrorStream(true); // merge syserr to sysout
        final Process p = pb.start();
        new Thread(new Runnable()
        if (exitValue != 0)
        {
          Cache.log.error("Command failed, return code = " + exitValue);
-         Cache.log.error("Command/args were: " + commands.toString());
+         Cache.log.error("Command/args were: " + args.toString());
        }
        return exitValue == 0; // 0 is success, by convention
      } catch (Exception e)
    }
  
    /**
-    * Converts the given command to a Cygwin "run" command wrapper
+    * Converts the given command to a Cygwin "bash" command wrapper. The hmmer
+    * command and any arguments to it are converted into a single parameter to the
+    * bash command.
     * 
-    * @param command
-    * @return
+    * @param commands
     */
-   protected List<String> wrapWithCygwin(List<String> command)
+   protected List<String> wrapWithCygwin(List<String> commands)
    {
-     File runCygwin = FileUtils.getExecutable("run",
+     File bash = FileUtils.getExecutable("bash",
              Cache.getProperty(Preferences.CYGWIN_PATH));
-     if (runCygwin == null)
+     if (bash == null)
      {
        Cache.log.error("Cygwin shell not found");
-       return command;
+       return commands;
      }
  
      List<String> wrapped = new ArrayList<>();
-     wrapped.add(runCygwin.getAbsolutePath());
-     if (!command.isEmpty())
+     wrapped.add(bash.getAbsolutePath());
+     wrapped.add("-c");
+     /*
+      * combine hmmbuild/search/align and arguments to a single string
+      */
+     StringBuilder sb = new StringBuilder();
+     for (String cmd : commands)
      {
-       wrapped.add(command.get(0));
-       // wrapped.add("--quote");
-       StringBuilder args = new StringBuilder();
-       for (String arg : command.subList(1, command.size()))
-       {
-         args.append(" ").append(arg);
-       }
-       wrapped.add(args.toString());
+       sb.append(" ").append(cmd);
      }
-     // TODO this doesn't yet pass parameters successfully
+     wrapped.add(sb.toString());
  
      return wrapped;
    }
      File file = FileUtils.getExecutable(cmd, binariesFolder);
      if (file == null && af != null)
      {
 -        JvOptionPane.showInternalMessageDialog(af,
 -                MessageManager.getString("warn.hmm_command_failed"));
 +      JvOptionPane.showInternalMessageDialog(af, MessageManager
 +              .formatMessage("label.executable_not_found", cmd));
      }
  
-     return file == null ? null : file.getAbsolutePath();
+     return file == null ? null : getFilePath(file);
    }
  
    /**
    }
  
    /**
 +   * Answers the HMM profile for the profile sequence the user selected (default
 +   * is just the first HMM sequence in the alignment)
 +   * 
 +   * @return
 +   */
 +  protected HiddenMarkovModel getHmmProfile()
 +  {
 +    String alignToParamName = MessageManager.getString("label.use_hmm");
 +    for (ArgumentI arg : params)
 +    {
 +      String name = arg.getName();
 +      if (name.equals(alignToParamName))
 +      {
 +        String seqName = arg.getValue();
 +        SequenceI hmmSeq = alignment.findName(seqName);
 +        if (hmmSeq.hasHMMProfile())
 +        {
 +          return hmmSeq.getHMM();
 +        }
 +      }
 +    }
 +    return null;
 +  }
++
++  /**
+    * Answers an absolute path to the given file, in a format suitable for
+    * processing by a hmmer command. On a Windows platform, the native Windows file
+    * path is converted to Cygwin format, by replacing '\'with '/' and drive letter
+    * X with /cygdrive/x.
+    * 
+    * @param resultFile
+    * @return
+    */
+   protected String getFilePath(File resultFile)
+   {
+     String path = resultFile.getAbsolutePath();
+     if (Platform.isWindows())
+     {
+       // the first backslash escapes '\' for the regular expression argument
+       path = path.replaceAll("\\" + File.separator, "/");
+       int colon = path.indexOf(':');
+       if (colon > 0)
+       {
+         String drive = path.substring(0, colon);
+         path = path.replaceAll(drive + ":", "/cygdrive/" + drive);
+       }
+     }
+     return path;
+   }
  }