From 863529ed7d15dd5812cf280d82bfd53734b424a1 Mon Sep 17 00:00:00 2001 From: kiramt Date: Tue, 14 Mar 2017 16:06:34 +0000 Subject: [PATCH] JAL-2388 New hidden cols/seqs functions to support overview panel --- src/jalview/datamodel/ColumnSelection.java | 86 ++++++++++++++++ src/jalview/datamodel/HiddenSequences.java | 35 +++++++ test/jalview/datamodel/ColumnSelectionTest.java | 59 +++++++++++ test/jalview/datamodel/HiddenSequencesTest.java | 123 ++++++++++++++++++----- 4 files changed, 277 insertions(+), 26 deletions(-) diff --git a/src/jalview/datamodel/ColumnSelection.java b/src/jalview/datamodel/ColumnSelection.java index 28745f1..56d9859 100644 --- a/src/jalview/datamodel/ColumnSelection.java +++ b/src/jalview/datamodel/ColumnSelection.java @@ -734,6 +734,63 @@ public class ColumnSelection } /** + * Find the visible column which is a given visible number of columns to the + * left of another visible column. i.e. for a startColumn x, the column which + * is distance 1 away will be column x-1. + * + * @param visibleDistance + * the number of visible columns to offset by + * @param startColumn + * the column to start from + * @return the position of the column in the visible alignment + */ + public int findColumnNToLeft(int visibleDistance, int startColumn) + { + int distance = visibleDistance; + + // in case startColumn is in a hidden region, move it to the left + int start = adjustForHiddenColumns(findColumnPosition(startColumn)); + + // get index of hidden region to left of start + int index = getHiddenIndexLeft(start); + if (index == -1) + { + // no hidden regions to left of startColumn + return start - distance; + } + + // walk backwards through the alignment subtracting the counts of visible + // columns from distance + int[] region; + int gap = 0; + int nextstart = start; + + while ((index > -1) && (distance - gap > 0)) + { + // subtract the gap to right of region from distance + distance -= gap; + start = nextstart; + + // calculate the next gap + region = hiddenColumns.get(index); + gap = start - region[1]; + + // set start to just to left of current region + nextstart = region[0] - 1; + index--; + } + + if (distance - gap > 0) + { + // fell out of loop because there are no more hidden regions + distance -= gap; + return nextstart - distance; + } + return start - distance; + + } + + /** * Use this method to determine where the next hiddenRegion starts * * @param hiddenRegion @@ -822,6 +879,35 @@ public class ColumnSelection } + /** + * This method returns the index of the hidden region to the left of a column + * position. If the column is in a hidden region it returns the index of the + * region to the left. If there is no hidden region to the left it returns -1. + * + * @param pos + * int + */ + private int getHiddenIndexLeft(int pos) + { + if (hiddenColumns != null) + { + int index = hiddenColumns.size() - 1; + do + { + int[] region = hiddenColumns.elementAt(index); + if (pos > region[1]) + { + return index; + } + + index--; + } while (index > -1); + } + + return -1; + + } + public void hideSelectedColumns() { synchronized (selection) diff --git a/src/jalview/datamodel/HiddenSequences.java b/src/jalview/datamodel/HiddenSequences.java index aca0be6..9c02f29 100755 --- a/src/jalview/datamodel/HiddenSequences.java +++ b/src/jalview/datamodel/HiddenSequences.java @@ -278,6 +278,41 @@ public class HiddenSequences } /** + * Find the visible row which is a given visible number of rows above another + * visible row. i.e. for a startRow x, the row which is distance 1 away will + * be row x-1. + * + * @param visibleDistance + * the number of visible rows to offset by + * @param startRow + * the row to start from + * @return the position of the row in the visible alignment + */ + public int findIndexNAboveRow(int visibleDistance, int startRow) + { + // walk upwards through the alignment + // count all the non-null sequences until we have visibleDistance counted + // then return the next visible sequence + if (hiddenSequences == null) + { + return startRow - visibleDistance; + } + + int index = startRow; + int count = 0; + while ((index > -1) && (count < visibleDistance)) + { + if (hiddenSequences[index] == null) + { + // count visible sequences + count++; + } + index--; + } + return index; + } + + /** * Convert alignment index from visible alignment to absolute alignment * * @param alignmentIndex diff --git a/test/jalview/datamodel/ColumnSelectionTest.java b/test/jalview/datamodel/ColumnSelectionTest.java index 5a915ce..49f29d7 100644 --- a/test/jalview/datamodel/ColumnSelectionTest.java +++ b/test/jalview/datamodel/ColumnSelectionTest.java @@ -140,6 +140,65 @@ public class ColumnSelectionTest } /** + * Test the method that finds the visible column position a given distance + * before another column + */ + @Test(groups = { "Functional" }) + public void testFindColumnNToLeft() + { + ColumnSelection cs = new ColumnSelection(); + + // test that without hidden columns, findColumnNToLeft returns + // position n to left of provided position + int pos = cs.findColumnNToLeft(3, 10); + assertEquals(7, pos); + + // 0 returns same position + pos = cs.findColumnNToLeft(0, 10); + assertEquals(10, pos); + + // overflow to left returns negative number + pos = cs.findColumnNToLeft(3, 0); + assertEquals(-3, pos); + + // test that with hidden columns to left of result column + // behaviour is the same as above + cs.hideColumns(1, 3); + + // position n to left of provided position + pos = cs.findColumnNToLeft(3, 10); + assertEquals(7, pos); + + // 0 returns same position + pos = cs.findColumnNToLeft(0, 10); + assertEquals(10, pos); + + // test with one set of hidden columns between start and required position + cs.hideColumns(12, 15); + pos = cs.findColumnNToLeft(8, 17); + assertEquals(5, pos); + + // test with two sets of hidden columns between start and required position + cs.hideColumns(20, 21); + pos = cs.findColumnNToLeft(8, 23); + assertEquals(9, pos); + + // repeat last 2 tests with no hidden columns to left of required position + cs.revealAllHiddenColumns(); + + // test with one set of hidden columns between start and required position + cs.hideColumns(12, 15); + pos = cs.findColumnNToLeft(8, 17); + assertEquals(5, pos); + + // test with two sets of hidden columns between start and required position + cs.hideColumns(20, 21); + pos = cs.findColumnNToLeft(8, 23); + assertEquals(9, pos); + + } + + /** * Test the code used to locate the reference sequence ruler origin */ @Test(groups = { "Functional" }) diff --git a/test/jalview/datamodel/HiddenSequencesTest.java b/test/jalview/datamodel/HiddenSequencesTest.java index b41b98f..a556458 100644 --- a/test/jalview/datamodel/HiddenSequencesTest.java +++ b/test/jalview/datamodel/HiddenSequencesTest.java @@ -49,7 +49,7 @@ public class HiddenSequencesTest JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); } - static int SEQ_COUNT = 10; + static int SEQ_COUNT = 25; SequenceI[] seqs; @@ -62,8 +62,9 @@ public class HiddenSequencesTest seqs = new SequenceI[SEQ_COUNT]; for (int i = 0; i < SEQ_COUNT; i++) { - // sequence lengths are 1, 2, ... 10 - seqs[i] = new Sequence("Seq" + i, "abcdefghijk".substring(0, i + 1)); + // sequence lengths are 1, 2, ... 25 + seqs[i] = new Sequence("Seq" + i, + "abcdefghijklmnopqrstuvwxy".substring(0, i + 1)); } } @@ -89,7 +90,7 @@ public class HiddenSequencesTest /* * alignment is now seq0/2/3/4/7/8/9 */ - assertEquals(7, al.getHeight()); + assertEquals(SEQ_COUNT - 3, al.getHeight()); assertEquals(0, hs.adjustForHiddenSeqs(0)); assertEquals(2, hs.adjustForHiddenSeqs(1)); assertEquals(3, hs.adjustForHiddenSeqs(2)); @@ -193,7 +194,7 @@ public class HiddenSequencesTest /* * alignment is now seq0/2/3/4/7/8/9 */ - assertEquals(7, al.getHeight()); + assertEquals(SEQ_COUNT - 3, al.getHeight()); assertEquals(0, hs.findIndexWithoutHiddenSeqs(0)); assertEquals(0, hs.findIndexWithoutHiddenSeqs(1)); assertEquals(1, hs.findIndexWithoutHiddenSeqs(2)); @@ -207,6 +208,76 @@ public class HiddenSequencesTest } /** + * Test the method that finds the visible row position a given distance before + * another row + */ + @Test(groups = { "Functional" }) + public void testFindIndexNFromRow() + { + AlignmentI al = new Alignment(seqs); + HiddenSequences hs = new HiddenSequences(al); + + // test that without hidden rows, findIndexNFromRow returns + // position n above provided position + int pos = hs.findIndexNAboveRow(3, 10); + assertEquals(7, pos); + + // 0 returns same position + pos = hs.findIndexNAboveRow(0, 10); + assertEquals(10, pos); + + // overflow to top returns negative number + pos = hs.findIndexNAboveRow(3, 0); + assertEquals(-3, pos); + + // test that with hidden rows above result row + // behaviour is the same as above + hs.hideSequence(seqs[1]); + hs.hideSequence(seqs[2]); + hs.hideSequence(seqs[3]); + + // position n above provided position + pos = hs.findIndexNAboveRow(3, 10); + assertEquals(7, pos); + + // 0 returns same position + pos = hs.findIndexNAboveRow(0, 10); + assertEquals(10, pos); + + // test with one set of hidden rows between start and required position + hs.hideSequence(seqs[12]); + hs.hideSequence(seqs[13]); + hs.hideSequence(seqs[14]); + hs.hideSequence(seqs[15]); + pos = hs.findIndexNAboveRow(8, 17); + assertEquals(5, pos); + + // test with two sets of hidden rows between start and required position + hs.hideSequence(seqs[20]); + hs.hideSequence(seqs[21]); + pos = hs.findIndexNAboveRow(8, 23); + assertEquals(9, pos); + + // repeat last 2 tests with no hidden columns to left of required position + hs.showAll(null); + + // test with one set of hidden rows between start and required position + hs.hideSequence(seqs[12]); + hs.hideSequence(seqs[13]); + hs.hideSequence(seqs[14]); + hs.hideSequence(seqs[15]); + pos = hs.findIndexNAboveRow(8, 17); + assertEquals(5, pos); + + // test with two sets of hidden rows between start and required position + hs.hideSequence(seqs[20]); + hs.hideSequence(seqs[21]); + pos = hs.findIndexNAboveRow(8, 23); + assertEquals(9, pos); + + } + + /** * Test the method that reconstructs (sort of) the full alignment including * hidden sequences */ @@ -289,7 +360,7 @@ public class HiddenSequencesTest assertTrue(al.getSequences().contains(seqs[1])); HiddenSequences hs = al.getHiddenSequences(); assertEquals(0, hs.getSize()); - assertEquals(10, al.getHeight()); + assertEquals(SEQ_COUNT, al.getHeight()); /* * hide the second sequence in the alignment @@ -299,7 +370,7 @@ public class HiddenSequencesTest assertTrue(hs.isHidden(seqs[1])); assertFalse(al.getSequences().contains(seqs[1])); assertEquals(1, hs.getSize()); - assertEquals(9, al.getHeight()); + assertEquals(SEQ_COUNT - 1, al.getHeight()); assertSame(seqs[2], al.getSequenceAt(1)); /* @@ -312,7 +383,7 @@ public class HiddenSequencesTest assertFalse(al.getSequences().contains(seqs[1])); assertFalse(al.getSequences().contains(seqs[2])); assertEquals(2, hs.getSize()); - assertEquals(8, al.getHeight()); + assertEquals(SEQ_COUNT - 2, al.getHeight()); /* * perform 'reveal' on what is now the second sequence in the alignment @@ -323,7 +394,7 @@ public class HiddenSequencesTest assertTrue(revealed.contains(seqs[1])); assertTrue(revealed.contains(seqs[2])); assertEquals(0, hs.getSize()); - assertEquals(10, al.getHeight()); + assertEquals(SEQ_COUNT, al.getHeight()); } /** @@ -338,39 +409,39 @@ public class HiddenSequencesTest assertTrue(al.getSequences().contains(seqs[1])); HiddenSequences hs = al.getHiddenSequences(); assertEquals(0, hs.getSize()); - assertEquals(10, al.getHeight()); + assertEquals(SEQ_COUNT, al.getHeight()); /* * hide the last sequence in the alignment */ - hs.hideSequence(seqs[9]); - assertFalse(hs.isHidden(seqs[8])); - assertTrue(hs.isHidden(seqs[9])); - assertFalse(al.getSequences().contains(seqs[9])); + hs.hideSequence(seqs[SEQ_COUNT - 1]); + assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2])); + assertTrue(hs.isHidden(seqs[SEQ_COUNT - 1])); + assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 1])); assertEquals(1, hs.getSize()); - assertEquals(9, al.getHeight()); + assertEquals(SEQ_COUNT - 1, al.getHeight()); /* * hide the third last sequence in the alignment */ - hs.hideSequence(seqs[7]); - assertFalse(hs.isHidden(seqs[8])); - assertTrue(hs.isHidden(seqs[7])); - assertFalse(al.getSequences().contains(seqs[7])); + hs.hideSequence(seqs[SEQ_COUNT - 3]); + assertFalse(hs.isHidden(seqs[SEQ_COUNT - 2])); + assertTrue(hs.isHidden(seqs[SEQ_COUNT - 3])); + assertFalse(al.getSequences().contains(seqs[SEQ_COUNT - 3])); assertEquals(2, hs.getSize()); - assertEquals(8, al.getHeight()); + assertEquals(SEQ_COUNT - 2, al.getHeight()); /* * reveal all the sequences, which should be reinstated in the same order as they started in */ hs.showAll(null); - assertFalse(hs.isHidden(seqs[7])); - assertFalse(hs.isHidden(seqs[9])); - assertEquals(seqs[7], al.getSequences().get(7)); - assertEquals(seqs[8], al.getSequences().get(8)); - assertEquals(seqs[9], al.getSequences().get(9)); + assertFalse(hs.isHidden(seqs[SEQ_COUNT - 3])); + assertFalse(hs.isHidden(seqs[SEQ_COUNT - 1])); + assertEquals(seqs[SEQ_COUNT - 3], al.getSequences().get(SEQ_COUNT - 3)); + assertEquals(seqs[SEQ_COUNT - 2], al.getSequences().get(SEQ_COUNT - 2)); + assertEquals(seqs[SEQ_COUNT - 1], al.getSequences().get(SEQ_COUNT - 1)); assertEquals(0, hs.getSize()); - assertEquals(10, al.getHeight()); + assertEquals(SEQ_COUNT, al.getHeight()); } @Test(groups = "Functional") -- 1.7.10.2