JAL-2388 last separation of hidden columns/col selection
authorkiramt <k.mourao@dundee.ac.uk>
Wed, 26 Apr 2017 13:35:14 +0000 (14:35 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Wed, 26 Apr 2017 13:35:14 +0000 (14:35 +0100)
src/jalview/appletgui/SeqPanel.java
src/jalview/datamodel/ColumnSelection.java
src/jalview/datamodel/HiddenColumns.java
src/jalview/gui/SeqPanel.java
src/jalview/ws/jws1/JPredThread.java
test/jalview/datamodel/ColumnSelectionTest.java

index ceae253..69a0dd0 100644 (file)
@@ -1878,7 +1878,8 @@ public class SeqPanel extends Panel implements MouseMotionListener,
         }
         else
         {
-          av.getColumnSelection().setElementsFrom(colsel);
+          av.getColumnSelection().setElementsFrom(colsel,
+                  av.getAlignment().getHiddenColumns());
         }
       }
       repaint |= av.isColSelChanged(true);
index 4d69fa4..eb2d174 100644 (file)
@@ -20,7 +20,6 @@
  */
 package jalview.datamodel;
 
-import jalview.util.ShiftList;
 import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
 import jalview.viewmodel.annotationfilter.AnnotationFilterParameter.SearchableAnnotationField;
 
@@ -266,8 +265,6 @@ public class ColumnSelection
 
   IntList selection = new IntList();
 
-  HiddenColumns hiddenColumns = new HiddenColumns();
-
   /**
    * Add a column to the selection
    * 
@@ -391,93 +388,6 @@ public class ColumnSelection
     return selection.getMinColumn();
   }
 
-  /**
-   * propagate shift in alignment columns to column selection
-   * 
-   * @param start
-   *          beginning of edit
-   * @param left
-   *          shift in edit (+ve for removal, or -ve for inserts)
-   */
-  /*  public List<int[]> compensateForEdit(int start, int change)
-    {
-      selection.compensateForEdits(start, change);
-      return hiddenColumns.compensateForEdit(start, change, this);
-    }
-  */
-  /**
-   * propagate shift in alignment columns to column selection special version of
-   * compensateForEdit - allowing for edits within hidden regions
-   * 
-   * @param start
-   *          beginning of edit
-   * @param left
-   *          shift in edit (+ve for removal, or -ve for inserts)
-   */
-  private void compensateForDelEdits(int start, int change)
-  {
-    selection.compensateForEdits(start, change);
-    hiddenColumns.compensateForDelEdits(start, change);
-  }
-
-  /**
-   * Adjust hidden column boundaries based on a series of column additions or
-   * deletions in visible regions.
-   * 
-   * @param shiftrecord
-   * @return
-   */
-  private ShiftList compensateForEdits(ShiftList shiftrecord)
-  {
-    if (shiftrecord != null)
-    {
-      final List<int[]> shifts = shiftrecord.getShifts();
-      if (shifts != null && shifts.size() > 0)
-      {
-        int shifted = 0;
-        for (int i = 0, j = shifts.size(); i < j; i++)
-        {
-          int[] sh = shifts.get(i);
-          compensateForDelEdits(shifted + sh[0], sh[1]);
-          shifted -= sh[1];
-        }
-      }
-      return shiftrecord.getInverse();
-    }
-    return null;
-  }
-
-
-  /**
-   * remove any hiddenColumns or selected columns and shift remaining based on a
-   * series of position, range deletions.
-   * 
-   * @param deletions
-   */
-  private void pruneDeletions(ShiftList deletions)
-  {
-    if (deletions != null)
-    {
-      final List<int[]> shifts = deletions.getShifts();
-      if (shifts != null && shifts.size() > 0)
-      {
-        hiddenColumns.pruneDeletions(shifts);
-
-        if (selection != null && selection.size() > 0)
-        {
-          selection.pruneColumnList(shifts);
-          if (selection != null && selection.size() == 0)
-          {
-            selection = null;
-          }
-        }
-        // and shift the rest.
-        this.compensateForEdits(deletions);
-      }
-    }
-  }
-
-
   public void hideSelectedColumns(AlignmentI al)
   {
     synchronized (selection)
@@ -590,33 +500,13 @@ public class ColumnSelection
   }
 
   /**
-   * add in any unselected columns from the given column selection, excluding
-   * any that are hidden.
-   * 
-   * @param colsel
-   */
-  public void addElementsFrom(ColumnSelection colsel)
-  {
-    if (colsel != null && !colsel.isEmpty())
-    {
-      for (Integer col : colsel.getSelected())
-      {
-        if (hiddenColumns != null
-                && hiddenColumns.isVisible(col.intValue()))
-        {
-          selection.add(col);
-        }
-      }
-    }
-  }
-
-  /**
-   * set the selected columns the given column selection, excluding any columns
-   * that are hidden.
+   * set the selected columns to the given column selection, excluding any
+   * columns that are hidden.
    * 
    * @param colsel
    */
-  public void setElementsFrom(ColumnSelection colsel)
+  public void setElementsFrom(ColumnSelection colsel,
+          HiddenColumns hiddenColumns)
   {
     selection = new IntList();
     if (colsel.selection != null && colsel.selection.size() > 0)
@@ -624,162 +514,27 @@ public class ColumnSelection
       if (hiddenColumns.hasHidden())
       {
         // only select visible columns in this columns selection
-        addElementsFrom(colsel);
-      }
-      else
-      {
-        // add everything regardless
         for (Integer col : colsel.getSelected())
         {
-          addElement(col);
-        }
-      }
-    }
-  }
-
-  /**
-   * Add gaps into the sequences aligned to profileseq under the given
-   * AlignmentView
-   * 
-   * @param profileseq
-   * @param al
-   *          - alignment to have gaps inserted into it
-   * @param input
-   *          - alignment view where sequence corresponding to profileseq is
-   *          first entry
-   * @return new Column selection for new alignment view, with insertions into
-   *         profileseq marked as hidden.
-   */
-  public static ColumnSelection propagateInsertions(SequenceI profileseq,
-          AlignmentI al, AlignmentView input)
-  {
-    int profsqpos = 0;
-
-    // return propagateInsertions(profileseq, al, )
-    char gc = al.getGapCharacter();
-    Object[] alandcolsel = input.getAlignmentAndHiddenColumns(gc);
-    ColumnSelection nview = (ColumnSelection) alandcolsel[1];
-    SequenceI origseq = ((SequenceI[]) alandcolsel[0])[profsqpos];
-    nview.propagateInsertions(profileseq, al, origseq);
-    return nview;
-  }
-
-  /**
-   * 
-   * @param profileseq
-   *          - sequence in al which corresponds to origseq
-   * @param al
-   *          - alignment which is to have gaps inserted into it
-   * @param origseq
-   *          - sequence corresponding to profileseq which defines gap map for
-   *          modifying al
-   */
-  private void propagateInsertions(SequenceI profileseq, AlignmentI al,
-          SequenceI origseq)
-  {
-    char gc = al.getGapCharacter();
-    // recover mapping between sequence's non-gap positions and positions
-    // mapping to view.
-    pruneDeletions(ShiftList.parseMap(origseq.gapMap()));
-    int[] viscontigs = hiddenColumns.getVisibleContigs(0,
-            profileseq.getLength());
-    int spos = 0;
-    int offset = 0;
-
-    // add profile to visible contigs
-    for (int v = 0; v < viscontigs.length; v += 2)
-    {
-      if (viscontigs[v] > spos)
-      {
-        StringBuffer sb = new StringBuffer();
-        for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)
-        {
-          sb.append(gc);
-        }
-        for (int s = 0, ns = al.getHeight(); s < ns; s++)
-        {
-          SequenceI sqobj = al.getSequenceAt(s);
-          if (sqobj != profileseq)
+          if (hiddenColumns != null
+                  && hiddenColumns.isVisible(col.intValue()))
           {
-            String sq = al.getSequenceAt(s).getSequenceAsString();
-            if (sq.length() <= spos + offset)
-            {
-              // pad sequence
-              int diff = spos + offset - sq.length() - 1;
-              if (diff > 0)
-              {
-                // pad gaps
-                sq = sq + sb;
-                while ((diff = spos + offset - sq.length() - 1) > 0)
-                {
-                  // sq = sq
-                  // + ((diff >= sb.length()) ? sb.toString() : sb
-                  // .substring(0, diff));
-                  if (diff >= sb.length())
-                  {
-                    sq += sb.toString();
-                  }
-                  else
-                  {
-                    char[] buf = new char[diff];
-                    sb.getChars(0, diff, buf, 0);
-                    sq += buf.toString();
-                  }
-                }
-              }
-              sq += sb.toString();
-            }
-            else
-            {
-              al.getSequenceAt(s).setSequence(
-                      sq.substring(0, spos + offset) + sb.toString()
-                              + sq.substring(spos + offset));
-            }
+            selection.add(col);
           }
         }
-        // offset+=sb.length();
-      }
-      spos = viscontigs[v + 1] + 1;
-    }
-    if ((offset + spos) < profileseq.getLength())
-    {
-      // pad the final region with gaps.
-      StringBuffer sb = new StringBuffer();
-      for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
-      {
-        sb.append(gc);
       }
-      for (int s = 0, ns = al.getHeight(); s < ns; s++)
+      else
       {
-        SequenceI sqobj = al.getSequenceAt(s);
-        if (sqobj == profileseq)
-        {
-          continue;
-        }
-        String sq = sqobj.getSequenceAsString();
-        // pad sequence
-        int diff = origseq.getLength() - sq.length();
-        while (diff > 0)
+        // add everything regardless
+        for (Integer col : colsel.getSelected())
         {
-          // sq = sq
-          // + ((diff >= sb.length()) ? sb.toString() : sb
-          // .substring(0, diff));
-          if (diff >= sb.length())
-          {
-            sq += sb.toString();
-          }
-          else
-          {
-            char[] buf = new char[diff];
-            sb.getChars(0, diff, buf, 0);
-            sq += buf.toString();
-          }
-          diff = origseq.getLength() - sq.length();
+          addElement(col);
         }
       }
     }
   }
 
+
   /**
    * 
    * @return true if there are columns marked
@@ -796,7 +551,6 @@ public class ColumnSelection
   {
     // JBPNote - this method needs to be refactored to become independent of
     // viewmodel package
-    hiddenColumns.revealAllHiddenColumns(this);
     this.clear();
     int count = 0;
     do
@@ -879,13 +633,12 @@ public class ColumnSelection
   }
 
   /**
-   * Returns a hashCode built from selected columns and hidden column ranges
+   * Returns a hashCode built from selected columns ranges
    */
   @Override
   public int hashCode()
   {
-    int hashCode = selection.hashCode();
-    return hiddenColumns.hashCode(hashCode);
+    return selection.hashCode();
   }
 
   /**
@@ -916,7 +669,7 @@ public class ColumnSelection
       return false;
     }
 
-    return this.hiddenColumns.equals(that.hiddenColumns);
+    return true;
   }
 
   /**
index 0b7e246..1abd04b 100644 (file)
@@ -1,6 +1,7 @@
 package jalview.datamodel;
 
 import jalview.util.Comparison;
+import jalview.util.ShiftList;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -1031,7 +1032,197 @@ public class HiddenColumns
   }
 
   /**
-   * Returns a hashCode built from selected columns and hidden column ranges
+   * Add gaps into the sequences aligned to profileseq under the given
+   * AlignmentView
+   * 
+   * @param profileseq
+   * @param al
+   *          - alignment to have gaps inserted into it
+   * @param input
+   *          - alignment view where sequence corresponding to profileseq is
+   *          first entry
+   * @return new HiddenColumns for new alignment view, with insertions into
+   *         profileseq marked as hidden.
+   */
+  public static HiddenColumns propagateInsertions(SequenceI profileseq,
+          AlignmentI al, AlignmentView input)
+  {
+    int profsqpos = 0;
+
+    char gc = al.getGapCharacter();
+    Object[] alandhidden = input.getAlignmentAndHiddenColumns(gc);
+    HiddenColumns nview = (HiddenColumns) alandhidden[1];
+    SequenceI origseq = ((SequenceI[]) alandhidden[0])[profsqpos];
+    nview.propagateInsertions(profileseq, al, origseq);
+    return nview;
+  }
+
+  /**
+   * 
+   * @param profileseq
+   *          - sequence in al which corresponds to origseq
+   * @param al
+   *          - alignment which is to have gaps inserted into it
+   * @param origseq
+   *          - sequence corresponding to profileseq which defines gap map for
+   *          modifying al
+   */
+  private void propagateInsertions(SequenceI profileseq, AlignmentI al,
+          SequenceI origseq)
+  {
+    char gc = al.getGapCharacter();
+    // recover mapping between sequence's non-gap positions and positions
+    // mapping to view.
+    pruneDeletions(ShiftList.parseMap(origseq.gapMap()));
+    int[] viscontigs = al.getHiddenColumns().getVisibleContigs(0,
+            profileseq.getLength());
+    int spos = 0;
+    int offset = 0;
+
+    // add profile to visible contigs
+    for (int v = 0; v < viscontigs.length; v += 2)
+    {
+      if (viscontigs[v] > spos)
+      {
+        StringBuffer sb = new StringBuffer();
+        for (int s = 0, ns = viscontigs[v] - spos; s < ns; s++)
+        {
+          sb.append(gc);
+        }
+        for (int s = 0, ns = al.getHeight(); s < ns; s++)
+        {
+          SequenceI sqobj = al.getSequenceAt(s);
+          if (sqobj != profileseq)
+          {
+            String sq = al.getSequenceAt(s).getSequenceAsString();
+            if (sq.length() <= spos + offset)
+            {
+              // pad sequence
+              int diff = spos + offset - sq.length() - 1;
+              if (diff > 0)
+              {
+                // pad gaps
+                sq = sq + sb;
+                while ((diff = spos + offset - sq.length() - 1) > 0)
+                {
+                  // sq = sq
+                  // + ((diff >= sb.length()) ? sb.toString() : sb
+                  // .substring(0, diff));
+                  if (diff >= sb.length())
+                  {
+                    sq += sb.toString();
+                  }
+                  else
+                  {
+                    char[] buf = new char[diff];
+                    sb.getChars(0, diff, buf, 0);
+                    sq += buf.toString();
+                  }
+                }
+              }
+              sq += sb.toString();
+            }
+            else
+            {
+              al.getSequenceAt(s).setSequence(
+                      sq.substring(0, spos + offset) + sb.toString()
+                              + sq.substring(spos + offset));
+            }
+          }
+        }
+        // offset+=sb.length();
+      }
+      spos = viscontigs[v + 1] + 1;
+    }
+    if ((offset + spos) < profileseq.getLength())
+    {
+      // pad the final region with gaps.
+      StringBuffer sb = new StringBuffer();
+      for (int s = 0, ns = profileseq.getLength() - spos - offset; s < ns; s++)
+      {
+        sb.append(gc);
+      }
+      for (int s = 0, ns = al.getHeight(); s < ns; s++)
+      {
+        SequenceI sqobj = al.getSequenceAt(s);
+        if (sqobj == profileseq)
+        {
+          continue;
+        }
+        String sq = sqobj.getSequenceAsString();
+        // pad sequence
+        int diff = origseq.getLength() - sq.length();
+        while (diff > 0)
+        {
+          // sq = sq
+          // + ((diff >= sb.length()) ? sb.toString() : sb
+          // .substring(0, diff));
+          if (diff >= sb.length())
+          {
+            sq += sb.toString();
+          }
+          else
+          {
+            char[] buf = new char[diff];
+            sb.getChars(0, diff, buf, 0);
+            sq += buf.toString();
+          }
+          diff = origseq.getLength() - sq.length();
+        }
+      }
+    }
+  }
+
+  /**
+   * remove any hiddenColumns or selected columns and shift remaining based on a
+   * series of position, range deletions.
+   * 
+   * @param deletions
+   */
+  private void pruneDeletions(ShiftList deletions)
+  {
+    if (deletions != null)
+    {
+      final List<int[]> shifts = deletions.getShifts();
+      if (shifts != null && shifts.size() > 0)
+      {
+        pruneDeletions(shifts);
+
+        // and shift the rest.
+        this.compensateForEdits(deletions);
+      }
+    }
+  }
+
+  /**
+   * Adjust hidden column boundaries based on a series of column additions or
+   * deletions in visible regions.
+   * 
+   * @param shiftrecord
+   * @return
+   */
+  private ShiftList compensateForEdits(ShiftList shiftrecord)
+  {
+    if (shiftrecord != null)
+    {
+      final List<int[]> shifts = shiftrecord.getShifts();
+      if (shifts != null && shifts.size() > 0)
+      {
+        int shifted = 0;
+        for (int i = 0, j = shifts.size(); i < j; i++)
+        {
+          int[] sh = shifts.get(i);
+          compensateForDelEdits(shifted + sh[0], sh[1]);
+          shifted -= sh[1];
+        }
+      }
+      return shiftrecord.getInverse();
+    }
+    return null;
+  }
+
+  /**
+   * Returns a hashCode built from hidden column ranges
    */
   public int hashCode(int hc)
   {
index 063ab7d..31fe2b6 100644 (file)
@@ -2044,7 +2044,8 @@ public class SeqPanel extends JPanel implements MouseListener,
         }
         else
         {
-          av.getColumnSelection().setElementsFrom(colsel);
+          av.getColumnSelection().setElementsFrom(colsel,
+                  av.getAlignment().getHiddenColumns());
         }
       }
       av.isColSelChanged(true);
index 078f189..b0210d8 100644 (file)
@@ -27,7 +27,6 @@ import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentView;
-import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
@@ -115,7 +114,7 @@ class JPredThread extends JWS1Thread implements WSClientI
         return null;
       }
       AlignmentI al = null;
-      ColumnSelection alcsel = null;
+      HiddenColumns alhidden = null;
       int FirstSeq = -1; // the position of the query sequence in Alignment al
 
       JpredResult result = (JpredResult) this.result;
@@ -145,7 +144,7 @@ class JPredThread extends JWS1Thread implements WSClientI
                     .getAlignmentAndHiddenColumns(getGapChar());
             sqs = (SequenceI[]) alandcolsel[0];
             al = new Alignment(sqs);
-            alcsel = (ColumnSelection) alandcolsel[1];
+            alhidden = (HiddenColumns) alandcolsel[1];
           }
           else
           {
@@ -238,7 +237,7 @@ class JPredThread extends JWS1Thread implements WSClientI
           {
             // Adjust input view for gaps
             // propagate insertions into profile
-            alcsel = ColumnSelection.propagateInsertions(profileseq, al,
+            alhidden = HiddenColumns.propagateInsertions(profileseq, al,
                     input);
           }
         }
@@ -253,7 +252,7 @@ class JPredThread extends JWS1Thread implements WSClientI
                   alant.sequenceRef);
         }
       }
-      return new Object[] { al, alcsel }; // , FirstSeq, noMsa};
+      return new Object[] { al, alhidden }; // , FirstSeq, noMsa};
     }
 
     /**
index e5f2daa..ce2949f 100644 (file)
@@ -59,6 +59,30 @@ public class ColumnSelectionTest
     assertEquals("[2, 5, 3]", sel.toString());
   }
 
+  @Test(groups = { "Functional" })
+  public void testSetElementsFrom()
+  {
+    ColumnSelection fromcs = new ColumnSelection();
+    ColumnSelection tocs = new ColumnSelection();
+    HiddenColumns hidden = new HiddenColumns();
+
+    fromcs.addElement(2);
+    fromcs.addElement(3);
+    fromcs.addElement(5);
+
+    tocs.setElementsFrom(fromcs, hidden);
+    assertTrue(tocs.equals(fromcs));
+
+    hidden.hideColumns(4, 6);
+    tocs.setElementsFrom(fromcs, hidden);
+
+    // expect cols 2 and 3 to be selected but not 5
+    ColumnSelection expectcs = new ColumnSelection();
+    expectcs.addElement(2);
+    expectcs.addElement(3);
+    assertTrue(tocs.equals(expectcs));
+  }
+
   /**
    * Test the remove method - in particular to verify that remove(int i) removes
    * the element whose value is i, _NOT_ the i'th element.