JAL-2174 markColumns() refactored inside ColumnSelection
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 23 Aug 2016 08:16:51 +0000 (09:16 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 23 Aug 2016 08:16:51 +0000 (09:16 +0100)
src/jalview/controller/AlignViewController.java
src/jalview/datamodel/ColumnSelection.java
test/jalview/controller/AlignViewControllerTest.java
test/jalview/datamodel/ColumnSelectionTest.java
test/jalview/datamodel/SequenceTest.java

index f966072..82c8d38 100644 (file)
@@ -182,14 +182,15 @@ public class AlignViewController implements AlignViewControllerI
 
     if (bs.cardinality() > 0 || invert)
     {
-      boolean changed = selectMarkedColumns(cs, invert, extendCurrent,
-              toggle, bs, sqcol.getStartRes(), sqcol.getEndRes());
+      boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
+              sqcol.getEndRes(), invert, extendCurrent, toggle);
       if (changed)
       {
         viewport.setColumnSelection(cs);
         alignPanel.paintAlignment(true);
         int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
-                - bs.cardinality() : bs.cardinality();
+                - bs.cardinality()
+                : bs.cardinality();
         avcg.setStatus(MessageManager.formatMessage(
                 "label.view_controller_toggled_marked",
                 new String[] {
@@ -198,8 +199,8 @@ public class AlignViewController implements AlignViewControllerI
                     String.valueOf(columnCount),
                     MessageManager
                             .getString(invert ? "label.not_containing"
-                                    : "label.containing"),
-                    featureType, Integer.valueOf(nseq).toString() }));
+                                    : "label.containing"), featureType,
+                    Integer.valueOf(nseq).toString() }));
         return true;
       }
     }
@@ -208,7 +209,7 @@ public class AlignViewController implements AlignViewControllerI
       avcg.setStatus(MessageManager.formatMessage(
               "label.no_feature_of_type_found",
               new String[] { featureType }));
-      if (!extendCurrent && cs != null)
+      if (!extendCurrent)
       {
         cs.clear();
         alignPanel.paintAlignment(true);
@@ -218,85 +219,9 @@ public class AlignViewController implements AlignViewControllerI
   }
 
   /**
-   * Updates the column selection depending on the parameters, and returns true
-   * if any change was made to the selection.
-   * 
-   * @param columnSelection
-   *          the current column selection
-   * @param invert
-   *          if true, deselect marked columns and select unmarked
-   * @param extendCurrent
-   *          if true, extend rather than replacing the current column selection
-   * @param toggle
-   *          if true, toggle the selection state of marked columns
-   * @param markedColumns
-   *          a set identify marked columns
-   * @param startCol
-   *          the first column of the range to operate over
-   * @param endCol
-   *          the last column of the range to operate over
-   * @return
-   */
-  static boolean selectMarkedColumns(ColumnSelection columnSelection,
-          boolean invert, boolean extendCurrent, boolean toggle,
-          BitSet markedColumns, int startCol, int endCol)
-  {
-    boolean changed = false;
-    if (!extendCurrent && !toggle)
-    {
-      changed = !columnSelection.isEmpty();
-      columnSelection.clear();
-    }
-    if (invert)
-    {
-      // invert only in the currently selected sequence region
-      int i = markedColumns.nextClearBit(startCol);
-      int ibs = markedColumns.nextSetBit(startCol);
-      while (i >= startCol && i <= endCol)
-      {
-        if (ibs < 0 || i < ibs)
-        {
-          changed = true;
-          if (toggle && columnSelection.contains(i))
-          {
-            columnSelection.removeElement(i++);
-          }
-          else
-          {
-            columnSelection.addElement(i++);
-          }
-        }
-        else
-        {
-          i = markedColumns.nextClearBit(ibs);
-          ibs = markedColumns.nextSetBit(i);
-        }
-      }
-    }
-    else
-    {
-      int i = markedColumns.nextSetBit(startCol);
-      while (i >= startCol && i <= endCol)
-      {
-        changed = true;
-        if (toggle && columnSelection.contains(i))
-        {
-          columnSelection.removeElement(i);
-        }
-        else
-        {
-          columnSelection.addElement(i);
-        }
-        i = markedColumns.nextSetBit(i + 1);
-      }
-    }
-    return changed;
-  }
-
-  /**
-   * Sets a bit in the BitSet for each column in the sequence collection which
-   * includes the specified feature type. Returns the number of sequences which
-   * have the feature in the selected range.
+   * Sets a bit in the BitSet for each column (base 0) in the sequence
+   * collection which includes the specified feature type. Returns the number of
+   * sequences which have the feature in the selected range.
    * 
    * @param featureType
    * @param sqcol
@@ -304,8 +229,7 @@ public class AlignViewController implements AlignViewControllerI
    * @return
    */
   static int findColumnsWithFeature(String featureType,
-          SequenceCollectionI sqcol,
-          BitSet bs)
+          SequenceCollectionI sqcol, BitSet bs)
   {
     final int startPosition = sqcol.getStartRes() + 1; // converted to base 1
     final int endPosition = sqcol.getEndRes() + 1;
@@ -319,6 +243,10 @@ public class AlignViewController implements AlignViewControllerI
         SequenceFeature[] sfs = sq.getSequenceFeatures();
         if (sfs != null)
         {
+          /*
+           * check whether the feature start/end (base 1) 
+           * overlaps the selection start/end
+           */
           int ist = sq.findIndex(sq.getStart());
           int iend = sq.findIndex(sq.getEnd());
           if (iend < startPosition || ist > endPosition)
@@ -358,7 +286,7 @@ public class AlignViewController implements AlignViewControllerI
               }
               for (; i <= j; i++)
               {
-                bs.set(i - 1);
+                bs.set(i - 1); // convert to base 0
               }
             }
           }
index 47acbd0..7ef2a68 100644 (file)
@@ -986,7 +986,7 @@ public class ColumnSelection
           SequenceI[] seqs)
   {
     int i, iSize = seqs.length;
-    String selection[] = new String[iSize];
+    String selections[] = new String[iSize];
     if (hiddenColumns != null && hiddenColumns.size() > 0)
     {
       for (i = 0; i < iSize; i++)
@@ -1028,18 +1028,18 @@ public class ColumnSelection
           visibleSeq.append(seqs[i].getSequence(blockStart, end));
         }
 
-        selection[i] = visibleSeq.toString();
+        selections[i] = visibleSeq.toString();
       }
     }
     else
     {
       for (i = 0; i < iSize; i++)
       {
-        selection[i] = seqs[i].getSequenceAsString(start, end);
+        selections[i] = seqs[i].getSequenceAsString(start, end);
       }
     }
 
-    return selection;
+    return selections;
   }
 
   /**
@@ -1704,4 +1704,78 @@ public class ColumnSelection
     return true;
   }
 
+  /**
+   * Updates the column selection depending on the parameters, and returns true
+   * if any change was made to the selection
+   * 
+   * @param markedColumns
+   *          a set identifying marked columns (base 0)
+   * @param startCol
+   *          the first column of the range to operate over (base 0)
+   * @param endCol
+   *          the last column of the range to operate over (base 0)
+   * @param invert
+   *          if true, deselect marked columns and select unmarked
+   * @param extendCurrent
+   *          if true, extend rather than replacing the current column selection
+   * @param toggle
+   *          if true, toggle the selection state of marked columns
+   * 
+   * @return
+   */
+  public boolean markColumns(BitSet markedColumns, int startCol,
+          int endCol, boolean invert, boolean extendCurrent, boolean toggle)
+  {
+    boolean changed = false;
+    if (!extendCurrent && !toggle)
+    {
+      changed = !this.isEmpty();
+      clear();
+    }
+    if (invert)
+    {
+      // invert only in the currently selected sequence region
+      int i = markedColumns.nextClearBit(startCol);
+      int ibs = markedColumns.nextSetBit(startCol);
+      while (i >= startCol && i <= endCol)
+      {
+        if (ibs < 0 || i < ibs)
+        {
+          changed = true;
+          if (toggle && contains(i))
+          {
+            removeElement(i++);
+          }
+          else
+          {
+            addElement(i++);
+          }
+        }
+        else
+        {
+          i = markedColumns.nextClearBit(ibs);
+          ibs = markedColumns.nextSetBit(i);
+        }
+      }
+    }
+    else
+    {
+      int i = markedColumns.nextSetBit(startCol);
+      while (i >= startCol && i <= endCol)
+      {
+        changed = true;
+        if (toggle && contains(i))
+        {
+          removeElement(i);
+        }
+        else
+        {
+          addElement(i);
+        }
+        i = markedColumns.nextSetBit(i + 1);
+      }
+    }
+    return changed;
+  }
+
 }
index d85b68f..3eefada 100644 (file)
@@ -3,14 +3,12 @@ package jalview.controller;
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
 
-import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 
 import java.util.BitSet;
-import java.util.List;
 
 import org.testng.annotations.Test;
 
@@ -37,7 +35,7 @@ public class AlignViewControllerTest
             0f, null));
 
     /*
-     * select the first three columns --> seq1 2-3
+     * select the first three columns --> Metal in seq1 2-3
      */
     SequenceGroup sg = new SequenceGroup();
     sg.setStartRes(0); // base 0
@@ -56,7 +54,7 @@ public class AlignViewControllerTest
     assertTrue(bs.get(2));
     
     /*
-     * select the first four columns: seq1 2:4, seq2 4:4
+     * select the first four columns: Metal in seq1 2:4, seq2 4:4
      */
     sg.setEndRes(3);
     bs.clear();
@@ -69,7 +67,7 @@ public class AlignViewControllerTest
     assertTrue(bs.get(3));
 
     /*
-     * select column 11: seq3 only
+     * select column 11: Metal in seq3 only
      */
     sg.setStartRes(10);
     sg.setEndRes(10);
@@ -99,100 +97,4 @@ public class AlignViewControllerTest
     assertEquals(0, seqCount);
     assertEquals(0, bs.cardinality());
   }
-
-  @Test(groups = "Functional")
-  public void testSelectMarkedColumns_invert()
-  {
-    ColumnSelection cs = new ColumnSelection();
-    cs.addElement(5); // this will be cleared
-    BitSet toMark = new BitSet();
-    toMark.set(1);
-    toMark.set(3);
-    toMark.set(6);
-    toMark.set(9);
-
-    /*
-     * inverted selection of {3, 6} should select {4, 5, 7, 8}
-     */
-    assertTrue(AlignViewController.selectMarkedColumns(cs, true, false,
-            false, toMark, 3, 8));
-    List<Integer> selected = cs.getSelected();
-    assertEquals(4, selected.size());
-    assertTrue(selected.contains(4));
-    assertTrue(selected.contains(5));
-    assertTrue(selected.contains(7));
-    assertTrue(selected.contains(8));
-  }
-
-  @Test(groups = "Functional")
-  public void testSelectMarkedColumns()
-  {
-    ColumnSelection cs = new ColumnSelection();
-    cs.addElement(5); // this will be cleared
-    BitSet toMark = new BitSet();
-    toMark.set(1);
-    toMark.set(3);
-    toMark.set(6);
-    toMark.set(9);
-  
-    assertTrue(AlignViewController.selectMarkedColumns(cs, false, false,
-            false, toMark, 3, 8));
-    List<Integer> selected = cs.getSelected();
-    assertEquals(2, selected.size());
-    assertTrue(selected.contains(3));
-    assertTrue(selected.contains(6));
-  }
-
-  @Test(groups = "Functional")
-  public void testSelectMarkedColumns_extend()
-  {
-    ColumnSelection cs = new ColumnSelection();
-    cs.addElement(1);
-    cs.addElement(5);
-    BitSet toMark = new BitSet();
-    toMark.set(1);
-    toMark.set(3);
-    toMark.set(6);
-    toMark.set(9);
-  
-    /*
-     * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
-     */
-    assertTrue(AlignViewController.selectMarkedColumns(cs, false, true,
-            false, toMark, 3, 8));
-    List<Integer> selected = cs.getSelected();
-    assertEquals(4, selected.size());
-    assertTrue(selected.contains(1));
-    assertTrue(selected.contains(3));
-    assertTrue(selected.contains(5));
-    assertTrue(selected.contains(6));
-  }
-
-  @Test(groups = "Functional")
-  public void testSelectMarkedColumns_toggle()
-  {
-    ColumnSelection cs = new ColumnSelection();
-    cs.addElement(1); // outside change range
-    cs.addElement(3);
-    cs.addElement(4);
-    cs.addElement(10); // outside change range
-    BitSet toMark = new BitSet();
-    toMark.set(1);
-    toMark.set(3);
-    toMark.set(6);
-    toMark.set(9);
-  
-    /*
-     * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
-     */
-    assertTrue(AlignViewController.selectMarkedColumns(cs, false, false,
-            true, toMark, 3, 8));
-    List<Integer> selected = cs.getSelected();
-    assertEquals(4, selected.size());
-    assertTrue(selected.contains(1));
-    assertTrue(selected.contains(4));
-    assertTrue(selected.contains(6));
-    assertTrue(selected.contains(10));
-  }
-  // TODO testSelectMarkedColumns with combinations of invert/extend/toggle set
 }
index 2deb1a7..e59719c 100644 (file)
@@ -27,6 +27,7 @@ import static org.testng.AssertJUnit.assertSame;
 import static org.testng.AssertJUnit.assertTrue;
 
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.List;
 
 import org.testng.annotations.Test;
@@ -577,4 +578,95 @@ public class ColumnSelectionTest
     assertEquals(21, selected3.get(1).intValue());
     assertEquals(1, selected3.get(2).intValue());
   }
+
+  @Test(groups = "Functional")
+  public void testMarkColumns()
+  {
+    ColumnSelection cs = new ColumnSelection();
+    cs.addElement(5); // this will be cleared
+    BitSet toMark = new BitSet();
+    toMark.set(1);
+    toMark.set(3);
+    toMark.set(6);
+    toMark.set(9);
+
+    assertTrue(cs.markColumns(toMark, 3, 8, false, false, false));
+    List<Integer> selected = cs.getSelected();
+    assertEquals(2, selected.size());
+    assertTrue(selected.contains(3));
+    assertTrue(selected.contains(6));
+  }
+
+  @Test(groups = "Functional")
+  public void testMarkColumns_extend()
+  {
+    ColumnSelection cs = new ColumnSelection();
+    cs.addElement(1);
+    cs.addElement(5);
+    BitSet toMark = new BitSet();
+    toMark.set(1);
+    toMark.set(3);
+    toMark.set(6);
+    toMark.set(9);
+
+    /*
+     * extending selection of {3, 6} should leave {1, 3, 5, 6} selected
+     */
+    assertTrue(cs.markColumns(toMark, 3, 8, false, true, false));
+    List<Integer> selected = cs.getSelected();
+    assertEquals(4, selected.size());
+    assertTrue(selected.contains(1));
+    assertTrue(selected.contains(3));
+    assertTrue(selected.contains(5));
+    assertTrue(selected.contains(6));
+  }
+
+  @Test(groups = "Functional")
+  public void testMarkColumns_invert()
+  {
+    ColumnSelection cs = new ColumnSelection();
+    cs.addElement(5); // this will be cleared
+    BitSet toMark = new BitSet();
+    toMark.set(1);
+    toMark.set(3);
+    toMark.set(6);
+    toMark.set(9);
+
+    /*
+     * inverted selection of {3, 6} should select {4, 5, 7, 8}
+     */
+    assertTrue(cs.markColumns(toMark, 3, 8, true, false, false));
+    List<Integer> selected = cs.getSelected();
+    assertEquals(4, selected.size());
+    assertTrue(selected.contains(4));
+    assertTrue(selected.contains(5));
+    assertTrue(selected.contains(7));
+    assertTrue(selected.contains(8));
+  }
+
+  @Test(groups = "Functional")
+  public void testMarkColumns_toggle()
+  {
+    ColumnSelection cs = new ColumnSelection();
+    cs.addElement(1); // outside change range
+    cs.addElement(3);
+    cs.addElement(4);
+    cs.addElement(10); // outside change range
+    BitSet toMark = new BitSet();
+    toMark.set(1);
+    toMark.set(3);
+    toMark.set(6);
+    toMark.set(9);
+
+    /*
+     * toggling state of {3, 6} should leave {1, 4, 6, 10} selected
+     */
+    assertTrue(cs.markColumns(toMark, 3, 8, false, false, true));
+    List<Integer> selected = cs.getSelected();
+    assertEquals(4, selected.size());
+    assertTrue(selected.contains(1));
+    assertTrue(selected.contains(4));
+    assertTrue(selected.contains(6));
+    assertTrue(selected.contains(10));
+  }
 }
index 71719dd..cfc4cbb 100644 (file)
@@ -110,8 +110,7 @@ public class SequenceTest
   {
     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
             1f);
-    AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
-            1f);
+    addAnnotation("label2", "desc2", "calcId2", 1f);
     AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3",
             1f);
     AlignmentAnnotation[] anns = seq.getAnnotation("label1");
@@ -133,16 +132,15 @@ public class SequenceTest
   @Test(groups = { "Functional" })
   public void testGetAlignmentAnnotations_forCalcIdAndLabel()
   {
-    AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
-            1f);
+    addAnnotation("label1", "desc1", "calcId1", 1f);
     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
             1f);
-    AlignmentAnnotation ann3 = addAnnotation("label2", "desc3", "calcId3",
-            1f);
+    addAnnotation("label2", "desc3", "calcId3", 1f);
     AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
             1f);
-    AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null, 1f);
-    AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3", 1f);
+    addAnnotation("label5", "desc3", null, 1f);
+    addAnnotation(null, "desc3", "calcId3", 1f);
+
     List<AlignmentAnnotation> anns = seq.getAlignmentAnnotations("calcId2",
             "label2");
     assertEquals(2, anns.size());