JAL-2629 fix for addHMMConsensus failing if no HMM sequences found
[jalview.git] / src / jalview / hmmer / HMMERCommands.java
index c8d26e4..913eee8 100644 (file)
@@ -5,161 +5,91 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenMarkovModel;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
-import jalview.io.DataSourceType;
-import jalview.io.FileFormat;
-import jalview.io.FileLoader;
 import jalview.io.HMMFile;
 import jalview.io.StockholmFile;
-import jalview.util.MessageManager;
 
 import java.io.BufferedReader;
-import java.io.FileNotFoundException;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
+import java.util.Hashtable;
 import java.util.List;
-import java.util.Map;
-
-import javax.swing.JOptionPane;
 
+/**
+ * Contains multiple commands and methods frequently used to run hmmbuild,
+ * hmmalign and hmmsearch
+ * 
+ * @author TZVanaalten
+ *
+ */
 public class HMMERCommands
 {
   // Path of hmmer binaries directory
-  private static final String HMMERFOLDER = "H:/Documents/";
+  String HMMERFOLDER = "/Documents/";
 
-  private static final String HMMALIGN = HMMERFOLDER + "hmmalign ";
+  public String JALVIEWDIRECTORY = System.getProperty("user.dir")
+          + "/";
 
-  private static final String HMMBUILD = HMMERFOLDER + "hmmbuild ";
+  public final String HMMALIGN = "/hmmalign ";
 
-  private static final String HMMSEARCH = HMMERFOLDER + "hmmsearch ";
+  public final String HMMBUILD = "/hmmbuild ";
 
-  private static final String JALVIEWDIRECTORY = "C:/Users/TZVanaalten/git/jalview/";
+  public final String HMMSEARCH = "/hmmsearch ";
 
-  private static final String HMMBUFFER = "src/jalview/hmmer/hmm_buffer.hmm ";
+  public String OUTPUTALIGNMENT;
 
-  private static final String ALIGNMENTBUFFER = "src/jalview/hmmer/alignment_buffer.sto ";
+  public final String NAME = "-n ";
 
-  private static final String ALIGNMENTINPUT = "src/jalview/hmmer/alignment_input.sto ";
+  public final String SPACE = " ";
 
-  private static final String OUTPUTALIGNMENT = "-o " + JALVIEWDIRECTORY
-          + ALIGNMENTINPUT;
+  public final String ALLCOL = "--allcol ";
 
-  private static final String NAME = "-n ";
+  public final String TRIM = "--trim ";
 
-  private static final String SPACE = " ";
+  public final String FORCEAMINO = "--amino ";
 
-  private static final String ALLCOL = "--allcol ";
+  public final String FORCEDNA = "--dna ";
 
-  private static final String TRIM = "--trim ";
+  public final String FORCERNA = "--rna ";
 
-  public static void hmmBuild(AlignFrame af)
-          throws IOException, InterruptedException
-  {
+  Hashtable hash = new Hashtable();
 
-    PrintWriter clearer = new PrintWriter(HMMBUFFER);
-    clearer.print("");
-    clearer.close();
-    AlignmentI alignment = af.getViewport().getAlignment();
-    if (!alignment.isAligned())
-    {
-      alignment.padGaps();
-    }
-    Map<Integer, SequenceI> seqs = alignment.getHMMConsensusSequences(true);
-    exportAlignment(alignment);
-    final String command = HMMBUILD + NAME + af.getName() + SPACE
-            + JALVIEWDIRECTORY + HMMBUFFER
-            + JALVIEWDIRECTORY + ALIGNMENTBUFFER;
+  List<SequenceI> hmmSeqs;
 
-    runCommand(command);
-
-    af.loadJalviewDataFile(HMMBUFFER, DataSourceType.FILE,
-            FileFormat.HMMER3, null);
-    for (Map.Entry<Integer, SequenceI> entry : seqs.entrySet())
-    {
-      SequenceI seq = entry.getValue();
-      Integer pos = entry.getKey();
-      addHMMConsensusSequence(af, seq, pos);
-    }
-    af.alignPanel.alignmentChanged();
+  /**
+   * Uniquifies the sequences when exporting and stores their details in a
+   * hashtable.
+   * 
+   * @param seqs
+   */
+  public void uniquifySequences(SequenceI[] seqs)
+  {
+    hash = jalview.analysis.SeqsetUtils.uniquify(seqs, true);
   }
 
-  public static void hmmAlign(AlignFrame af, boolean createNewFrame,
-          HiddenMarkovModel hmm)
-          throws IOException, InterruptedException
+  /**
+   * Recover the sequence data lost by uniquifying.
+   * 
+   * @param seqs
+   */
+  public void recoverSequenceNames(SequenceI[] seqs)
   {
-
-    PrintWriter clearer = new PrintWriter(ALIGNMENTINPUT);
-    clearer.print("");
-    clearer.close();
-    AlignmentI al = af.getViewport().getAlignment();
-    if (!al.isAligned())
-    {
-      al.padGaps();
-    }
-    Map<Integer, SequenceI> seqs = al.getHMMConsensusSequences(true);
-    int index = 0;
-    if (hmm == null)
-    {
-      JOptionPane.showMessageDialog(af,
-              MessageManager.getString("warn.null_hmm"));
-      return;
-    }
-    exportAlignment(al);
-
-    HMMFile file = new HMMFile(hmm);
-    file.exportFile(HMMBUFFER);
-
-    String command = HMMALIGN;
-    if (!hmm.getFileHeader().contains("HMMER3/f"))
-    {
-      command += ALLCOL;
-    }
-    command += TRIM + OUTPUTALIGNMENT + JALVIEWDIRECTORY + HMMBUFFER
-            + JALVIEWDIRECTORY + ALIGNMENTBUFFER;
-
-    runCommand(command);
-
-    if (createNewFrame)
-    {
-      FileLoader loader = new FileLoader();
-      AlignFrame newFrame = loader.LoadFileWaitTillLoaded(ALIGNMENTINPUT,
-            DataSourceType.FILE);
-      for (Map.Entry<Integer, SequenceI> entry : seqs.entrySet())
-      {
-        SequenceI seq = entry.getValue();
-        Integer pos = entry.getKey();
-        addHMMConsensusSequence(newFrame, seq, pos);
-      }
-      newFrame.alignPanel.alignmentChanged();
-    }
-    else
-    {
-      af.getViewport().getAlignment().getSequences().clear();
-      af.loadJalviewDataFile(ALIGNMENTBUFFER, DataSourceType.FILE,
-              FileFormat.Stockholm, null);
-      for (Map.Entry<Integer, SequenceI> entry : seqs.entrySet())
-      {
-        SequenceI seq = entry.getValue();
-        Integer pos = entry.getKey();
-        addHMMConsensusSequence(af, seq, pos);
-      }
-
-    }
-
-
+    jalview.analysis.SeqsetUtils.deuniquify(hash, seqs);
   }
 
-
   /**
-   * Runs a command in the terminal.
+   * Runs a command in the command line.
    * 
    * @param command
    * @throws IOException
    * @throws InterruptedException
    */
-  private static void runCommand(String command)
+  public boolean runCommand(String command)
           throws IOException, InterruptedException
   {
+    try
+    {
     final Process p = Runtime.getRuntime().exec(command);
 
     new Thread(new Runnable()
@@ -185,39 +115,84 @@ public class HMMERCommands
     }).start();
 
     p.waitFor();
+    } catch (Exception e)
+    {
+      e.printStackTrace();
+      return false;
+    }
+    return true;
   }
 
   /**
-   * Exports an alignment to the buffer location in Jalview.
+   * Exports an alignment and/or HMM to the specified file.
    * 
    * @param alignment
-   * @throws FileNotFoundException
+   * @throws IOException
    */
-  private static void exportAlignment(AlignmentI alignment)
-          throws FileNotFoundException
+  public void exportData(SequenceI[] seqs,
+          File stoLocation, HiddenMarkovModel hmm, File hmmLocation)
+          throws IOException
   {
-    List<SequenceI> list = alignment.getSequences();
-    SequenceI[] array = new SequenceI[list.size()];
-    list.toArray(array);
-
-    StockholmFile file = new StockholmFile(new Alignment(array));
-    file.setSeqs(array);
-    String output = file.print();
-    PrintWriter writer = new PrintWriter(ALIGNMENTBUFFER);
-    writer.println(output);
-    writer.close();
+    if (seqs != null)
+    {
+      StockholmFile file = new StockholmFile(new Alignment(seqs));
+      String output = file.print(seqs, false);
+      PrintWriter writer = new PrintWriter(stoLocation);
+      writer.println(output);
+      writer.close();
+    }
+
+    if (hmm != null)
+    {
+      HMMFile file = new HMMFile(hmm);
+      PrintWriter writer = new PrintWriter(hmmLocation);
+      writer.print(file.print());
+      writer.close();
+    }
   }
 
-  private static void addHMMConsensusSequence(AlignFrame af, SequenceI seq,
-          Integer position)
+  /**
+   * Adds any HMM sequences removed before submitting the alignment as a job
+   * back into the alignment.
+   * 
+   * @param af
+   */
+  public void addHMMConsensusSequences(AlignFrame af)
   {
-    seq.getHMM().initHMMSequence(af, position);
     AlignmentI al = af.getViewport().getAlignment();
+    if (hmmSeqs == null || hmmSeqs.size() < 1)
+    {
+      return;
+    }
+    for (SequenceI seq : hmmSeqs)
+    {
+      Integer position = seq.getPreviousPosition();
+      al.getSequences().add(position, seq);
+    }
     af.getViewport().setAlignment(al);
     af.alignPanel.adjustAnnotationHeight();
     af.getViewport().updateSequenceIdColours();
     af.buildSortByAnnotationScoresMenu();
+    af.getViewport().initInformation();
   }
 
+  /**
+   * Returns the list of HMM sequences removed
+   * 
+   * @return
+   */
+  public List<SequenceI> getHmmSeqs()
+  {
+    return hmmSeqs;
+  }
 
+  /**
+   * Sets the list of removed HMM sequences
+   * 
+   * @param hmmSeqs
+   */
+  public void setHmmSeqs(List<SequenceI> hmmSeqs)
+  {
+    this.hmmSeqs = hmmSeqs;
+  }
 }