JAL-2629 default HMMBuild to alignment if not specified by args
[jalview.git] / src / jalview / hmmer / HMMBuild.java
index 373c160..6de7029 100644 (file)
@@ -8,11 +8,11 @@ import jalview.datamodel.AnnotatedCollectionI;
 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.FileUtils;
 import jalview.util.MessageManager;
 import jalview.ws.params.ArgumentI;
 
@@ -20,7 +20,6 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -56,7 +55,7 @@ public class HMMBuild extends HmmerCommand
   @Override
   public void run()
   {
-    if (params == null)
+    if (params == null || params.isEmpty())
     {
       Cache.log.error("No parameters to HMMBuild!|");
       return;
@@ -66,7 +65,7 @@ public class HMMBuild extends HmmerCommand
     af.setProgressBar(MessageManager.getString("status.running_hmmbuild"),
             msgID);
 
-    AlignViewport viewport = af.getViewport();
+    AlignViewportI viewport = af.getViewport();
     try
     {
       /*
@@ -97,11 +96,14 @@ public class HMMBuild extends HmmerCommand
           AlignViewportI viewport)
   {
     List<AnnotatedCollectionI> runBuildFor = new ArrayList<>();
+    boolean foundArg = false;
+
     for (ArgumentI arg : params)
     {
       String name = arg.getName();
       if (MessageManager.getString("label.hmmbuild_for").equals(name))
       {
+        foundArg = true;
         String value = arg.getValue();
         if (MessageManager.getString("label.alignment").equals(value))
         {
@@ -135,6 +137,15 @@ public class HMMBuild extends HmmerCommand
         }
       }
     }
+
+    /*
+     * default is to build for the whole alignment
+     */
+    if (!foundArg)
+    {
+      runBuildFor.add(alignment);
+    }
+
     return runBuildFor;
   }
 
@@ -149,11 +160,8 @@ public class HMMBuild extends HmmerCommand
     File alignmentFile = null;
     try
     {
-      hmmFile = createTempFile("hmm", ".hmm");
-      alignmentFile = createTempFile("output", ".sto");
-      List<SequenceI> seqs = ac.getSequences();
-      List<SequenceI> copy = new ArrayList<>();
-      copy.addAll(seqs);
+      hmmFile = FileUtils.createTempFile("hmm", ".hmm");
+      alignmentFile = FileUtils.createTempFile("output", ".sto");
 
       if (ac instanceof Alignment)
       {
@@ -165,21 +173,20 @@ public class HMMBuild extends HmmerCommand
         }
       }
 
-      /*
-       * copy over sequences, excluding hmm consensus sequences
-       * hmm sequences are also deleted in preparation for 
-       * re-adding them when recalculated; Information annotation is not
-       * deleted, it will be updated to reference the new hmm sequence
-       * by InformationThread.findOrCreateAnnotation
-       */
-      Iterator<SequenceI> it = copy.iterator();
-      while (it.hasNext())
+      deleteHmmSequences(ac);
+
+      List<SequenceI> copy = new ArrayList<>();
+      if (ac instanceof Alignment)
+      {
+        copy.addAll(ac.getSequences());
+      }
+      else
       {
-        SequenceI seq = it.next();
-        if (seq.isHMMConsensusSequence())
+        SequenceI[] sel = ((SequenceGroup) ac)
+                .getSelectionAsNewSequences((AlignmentI) ac.getContext());
+        for (SequenceI seq : sel)
         {
-          alignment.deleteSequence(seq);
-          it.remove();
+          copy.add(seq);
         }
       }
 
@@ -188,11 +195,13 @@ public class HMMBuild extends HmmerCommand
 
       exportStockholm(copyArray, alignmentFile, ac);
 
-      recoverSequences(sequencesHash, seqs.toArray(new SequenceI[] {}));
+      recoverSequences(sequencesHash, copy.toArray(new SequenceI[] {}));
 
       boolean ran = runCommand(alignmentFile, hmmFile, ac);
       if (!ran)
       {
+        JvOptionPane.showInternalMessageDialog(af, MessageManager
+                .formatMessage("warn.command_failed", "hmmbuild"));
         return;
       }
       importData(hmmFile, ac);
@@ -213,6 +222,33 @@ public class HMMBuild extends HmmerCommand
   }
 
   /**
+   * A helper method that deletes any HMM consensus sequence from the given
+   * collection, and from the parent alignment if <code>ac</code> is a subgroup
+   * 
+   * @param ac
+   */
+  void deleteHmmSequences(AnnotatedCollectionI ac)
+  {
+    List<SequenceI> hmmSeqs = ac.getHmmSequences();
+    for (SequenceI hmmSeq : hmmSeqs)
+    {
+      if (ac instanceof SequenceGroup)
+      {
+        ((SequenceGroup) ac).deleteSequence(hmmSeq, false);
+        AnnotatedCollectionI context = ac.getContext();
+        if (context != null && context instanceof AlignmentI)
+        {
+          ((AlignmentI) context).deleteSequence(hmmSeq);
+        }
+      }
+      else
+      {
+        ((AlignmentI) ac).deleteSequence(hmmSeq);
+      }
+    }
+  }
+
+  /**
    * Constructs and executes the hmmbuild command as a separate process
    * 
    * @param sequencesFile
@@ -240,7 +276,7 @@ public class HMMBuild extends HmmerCommand
      * HMM name (will be given to consensus sequence) is
      * - as specified by an input parameter if set
      * - else group name with _HMM appended (if for a group)
-     * - else align fame title with _HMM appended (if title is not too long)
+     * - else align frame title with _HMM appended (if title is not too long)
      * - else "Alignment_HMM" 
      */
     String name = "";
@@ -290,8 +326,8 @@ public class HMMBuild extends HmmerCommand
       args.add(ARG_DNA);
     }
 
-    args.add(hmmFile.getAbsolutePath());
-    args.add(sequencesFile.getAbsolutePath());
+    args.add(getFilePath(hmmFile));
+    args.add(getFilePath(sequencesFile));
 
     return runCommand(args);
   }
@@ -309,34 +345,38 @@ public class HMMBuild extends HmmerCommand
   private void importData(File hmmFile, AnnotatedCollectionI ac)
           throws IOException
   {
+    if (hmmFile.length() == 0L)
+    {
+      Cache.log.error("Error: hmmbuild produced empty hmm file");
+      return;
+    }
+
     HMMFile file = new HMMFile(
             new FileParse(hmmFile.getAbsolutePath(), DataSourceType.FILE));
-    SequenceI[] seqs = file.getSeqsAsArray();
-    SequenceI hmmSeq = seqs[0];
-    hmmSeq.createDatasetSequence();
+    SequenceI hmmSeq = file.getHMM().getConsensusSequence();
+
+    if (hmmSeq == null)
+    {
+      // hmmbuild failure not detected earlier
+      return;
+    }
+
     if (ac instanceof SequenceGroup)
     {
       SequenceGroup grp = (SequenceGroup) ac;
-      hmmSeq.insertCharAt(0, ac.getStartRes(), '-');
+      char gapChar = alignment.getGapCharacter();
+      hmmSeq.insertCharAt(0, ac.getStartRes(), gapChar);
       hmmSeq.insertCharAt(ac.getEndRes() + 1,
-              alignment.getWidth() - ac.getEndRes() - 1, '-');
-      hmmSeq.updateHMMMapping();
+              alignment.getWidth() - ac.getEndRes() - 1, gapChar);
       SequenceI topSeq = grp.getSequencesInOrder(alignment)[0];
       int topIndex = alignment.findIndex(topSeq);
       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);
     }
   }
 }