Merge branch 'develop' into features/JAL-250_hideredundantseqs
[jalview.git] / src / jalview / gui / RedundancyPanel.java
index 8bf2fba..37458a7 100755 (executable)
@@ -29,8 +29,10 @@ import jalview.datamodel.SequenceI;
 import jalview.jbgui.GSliderPanel;
 import jalview.util.MessageManager;
 
+import java.awt.Color;
 import java.awt.event.ActionEvent;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Stack;
 import java.util.Vector;
@@ -66,6 +68,8 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
 
   Vector redundantSeqs;
 
+  private SequenceI[] redreps;
+
   /**
    * Creates a new RedundancyPanel object.
    * 
@@ -90,7 +94,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
       }
     });
 
-    applyButton.setText(MessageManager.getString("action.remove"));
+    applyButton.setText(MessageManager.getString("action.hide"));
     allGroupsCheck.setVisible(false);
     slider.setMinimum(0);
     slider.setMaximum(100);
@@ -168,9 +172,13 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
     {
       omitHidden = ap.av.getViewAsString(sg != null);
     }
-    redundancy = AlignSeq.computeRedundancyMatrix(originalSequences,
+    Object rr[] = AlignSeq.computeRedundancyMatrixWithRep(
+            originalSequences,
             omitHidden, start, end, false);
 
+    redundancy = (float[]) rr[0];
+    redreps = (SequenceI[]) rr[1];
+
     progress.setIndeterminate(false);
     progress.setVisible(false);
     progress = null;
@@ -214,21 +222,103 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
   @Override
   public void applyButton_actionPerformed(ActionEvent e)
   {
-    Vector del = new Vector();
 
     undoButton.setEnabled(true);
 
     float value = slider.getValue();
     SequenceGroup sg = ap.av.getSelectionGroup();
-
+    // delete_seqs(value, sg);
+    hide_seqs(value, sg);
+  }
+  private void hide_seqs(float value, SequenceGroup sg)
+  {
+    /**
+     * hash to look up the representative for a sequence
+     */
+    HashMap<SequenceI, SequenceI> rep = new HashMap<SequenceI, SequenceI>();
+    /**
+     * hash to collect lists of sequences represented by a sequence
+     */
+    HashMap<SequenceI, SequenceGroup> reps = new HashMap<SequenceI, SequenceGroup>();
     for (int i = 0; i < redundancy.length; i++)
     {
       if (value <= redundancy[i])
       {
-        del.addElement(originalSequences[i]);
+        // does this sequence represent other sequences ?
+        SequenceGroup repset;
+        // is the representative also redundant ?
+        SequenceI repForI = rep.get(redreps[i]);
+        if (repForI==null) {
+          // the representative is still in the alignment. 
+          // is it representing anything already ? 
+          repset = reps.get(redreps[i]);
+          if (repset==null)
+          {
+            repset = new SequenceGroup();
+          }
+          repset.addSequence(originalSequences[i], false);
+          rep.put(originalSequences[i], redreps[i]);
+          reps.put(redreps[i], repset);
+          // and save the representative sequence for originalSeq
+          repForI = redreps[i];
+        } else {
+          // already hidden the representative for this sequence, so look up its redundant peers
+          repset = reps.get(repForI);
+          if (repset==null)
+          {
+            throw new Error("Implementation failure for redundancy set creation");
+          }
+          // add the sequence to the peerset, and mark sequence's representative in hash
+          repset.addSequence(originalSequences[i], false);
+          rep.put(originalSequences[i], repForI);
+        }
+        // merge any sequences represented by this with its new containing group
+        SequenceGroup existingreps = reps.remove(originalSequences[i]);
+        if (existingreps!=null)
+        {
+          for (SequenceI sq:existingreps.getSequences())
+          {
+            rep.put(sq, repForI);
+            repset.addSequence(sq, false);
+          }
+        }
       }
     }
+    int s = 0, e = ap.av.getAlignment().getWidth();
+    if (sg != null)
+    {
+      s = sg.getStartRes();
+      e = sg.getEndRes();
+    }
+    List<SequenceGroup> sgs = new ArrayList<SequenceGroup>();
+    for (SequenceI repseq: reps.keySet())
+    {
+      sg = reps.get(repseq);
+      sg.addSequence(repseq, false);
+      sg.setSeqrep(repseq);
+      sg.setStartRes(s);
+      sg.setEndRes(e);
+      sgs.add(sg);
+    }
+    ap.alignFrame.avc.showRandomColoursForGroups(sgs);
+    for (SequenceI repseq : reps.keySet())
+    {
+      sg = reps.get(repseq);
+      ap.av.hideRepSequences(repseq, sg);
+    }
+  }
+
+  private void delete_seqs(float value, SequenceGroup sg)
+  {
+    ArrayList<SequenceI> del = new ArrayList<SequenceI>();
 
+    for (int i = 0; i < redundancy.length; i++)
+    {
+      if (value <= redundancy[i])
+      {
+        del.add(originalSequences[i]);
+      }
+    }
     // This has to be done before the restoreHistoryItem method of alignFrame
     // will
     // actually restore these sequences.
@@ -239,7 +329,7 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
       int width = 0;
       for (int i = 0; i < del.size(); i++)
       {
-        deleted[i] = (SequenceI) del.elementAt(i);
+        deleted[i] = del.get(i);
         if (deleted[i].getLength() > width)
         {
           width = deleted[i].getLength();
@@ -303,4 +393,23 @@ public class RedundancyPanel extends GSliderPanel implements Runnable
     }
   }
 
+  /**
+   * DOCUMENT ME!
+   * 
+   * @param e
+   *          DOCUMENT ME!
+   */
+  @Override
+  public void valueField_actionPerformed(ActionEvent e)
+  {
+    try
+    {
+      int i = Integer.parseInt(valueField.getText());
+      slider.setValue(i);
+    } catch (Exception ex)
+    {
+      valueField.setText(slider.getValue() + "");
+    }
+  }
+
 }