/*
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* This file is part of Jalview.
*
* Jalview is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* Jalview is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jalview. If not, see .
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.datamodel;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
import java.util.Arrays;
import java.util.List;
import org.testng.annotations.Test;
public class ColumnSelectionTest
{
@Test(groups = { "Functional" })
public void testAddElement()
{
ColumnSelection cs = new ColumnSelection();
cs.addElement(2);
cs.addElement(5);
cs.addElement(3);
cs.addElement(5); // ignored
List sel = cs.getSelected();
assertEquals("[2, 5, 3]", sel.toString());
}
/**
* Test the remove method - in particular to verify that remove(int i) removes
* the element whose value is i, _NOT_ the i'th element.
*/
@Test(groups = { "Functional" })
public void testRemoveElement()
{
ColumnSelection cs = new ColumnSelection();
cs.addElement(2);
cs.addElement(5);
// removing elements not in the list has no effect
cs.removeElement(0);
cs.removeElement(1);
List sel = cs.getSelected();
assertEquals(2, sel.size());
assertEquals(new Integer(2), sel.get(0));
assertEquals(new Integer(5), sel.get(1));
// removing an element in the list removes it
cs.removeElement(2);
assertEquals(1, sel.size());
assertEquals(new Integer(5), sel.get(0));
}
/**
* Test the method that finds the visible column position of an alignment
* column, allowing for hidden columns.
*/
@Test(groups = { "Functional" })
public void testFindColumnPosition()
{
ColumnSelection cs = new ColumnSelection();
assertEquals(5, cs.findColumnPosition(5));
// hiding column 6 makes no difference
cs.hideColumns(6, 6);
assertEquals(5, cs.findColumnPosition(5));
// hiding column 4 moves column 5 to column 4
cs.hideColumns(4, 4);
assertEquals(4, cs.findColumnPosition(5));
// hiding columns 1 and 2 moves column 5 to column 2
cs.hideColumns(1, 2);
assertEquals(2, cs.findColumnPosition(5));
}
/**
* Test the code used to locate the reference sequence ruler origin
*/
@Test(groups = { "Functional" })
public void testLocateVisibleBoundsofSequence()
{
ColumnSelection cs = new ColumnSelection();
SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---");
assertEquals(2, seq.findIndex(seq.getStart()));
// no hidden columns
assertEquals(
Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1 }),
Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
// hidden column on gap after end of sequence - should not affect bounds
cs.hideColumns(13);
assertEquals(
Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1, seq.getStart(),
seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1 }),
Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
cs.revealAllHiddenColumns();
// hidden column on gap before beginning of sequence - should vis bounds by
// one
cs.hideColumns(0);
assertEquals(
Arrays.toString(new int[] { seq.findIndex(seq.getStart()) - 2,
seq.findIndex(seq.getEnd()) - 2, seq.getStart(),
seq.getEnd(), seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1 }),
Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
cs.revealAllHiddenColumns();
// hide columns around most of sequence - leave one residue remaining
cs.hideColumns(1, 3);
cs.hideColumns(6, 11);
assertEquals("-D",
cs.getVisibleSequenceStrings(0, 5, new SequenceI[] { seq })[0]);
assertEquals(
Arrays.toString(new int[] { 1, 1, 3, 3,
seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1 }),
Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
cs.revealAllHiddenColumns();
// hide whole sequence - should just get location of hidden region
// containing sequence
cs.hideColumns(1, 11);
assertEquals(
Arrays.toString(new int[] { 0, 1, 0, 0,
seq.findIndex(seq.getStart()) - 1,
seq.findIndex(seq.getEnd()) - 1 }),
Arrays.toString(cs.locateVisibleBoundsOfSequence(seq)));
}
@Test(groups={"Functional"})
public void testLocateVisibleBoundsPathologicals()
{
// test some pathological cases we missed
AlignmentI al = new Alignment(new SequenceI[] { new Sequence("refseqGaptest","KTDVTI----------NFI-----G----L")});
ColumnSelection cs = new ColumnSelection();
cs.hideInsertionsFor(al.getSequenceAt(0));
assertEquals(
"G",
""
+ al.getSequenceAt(0).getCharAt(
cs.adjustForHiddenColumns(9)));
}
@Test(groups = { "Functional" })
public void testHideColumns()
{
ColumnSelection cs = new ColumnSelection();
cs.hideColumns(5);
List hidden = cs.getHiddenColumns();
assertEquals(1, hidden.size());
assertEquals("[5, 5]", Arrays.toString(hidden.get(0)));
cs.hideColumns(3);
assertEquals(2, hidden.size());
// two hidden ranges, in order:
assertSame(hidden, cs.getHiddenColumns());
assertEquals("[3, 3]", Arrays.toString(hidden.get(0)));
assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
// hiding column 4 expands [3, 3] to [3, 4]
// not fancy enough to coalesce this into [3, 5] though
cs.hideColumns(4);
hidden = cs.getHiddenColumns();
assertEquals(2, hidden.size());
assertEquals("[3, 4]", Arrays.toString(hidden.get(0)));
assertEquals("[5, 5]", Arrays.toString(hidden.get(1)));
// clear hidden columns (note they are added to selected)
cs.revealAllHiddenColumns();
// it is now actually null but getter returns an empty list
assertTrue(cs.getHiddenColumns().isEmpty());
cs.hideColumns(3, 6);
hidden = cs.getHiddenColumns();
int[] firstHiddenRange = hidden.get(0);
assertEquals("[3, 6]", Arrays.toString(firstHiddenRange));
// adding a subrange of already hidden should do nothing
cs.hideColumns(4, 5);
assertEquals(1, hidden.size());
assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
cs.hideColumns(3, 5);
assertEquals(1, hidden.size());
assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
cs.hideColumns(4, 6);
assertEquals(1, hidden.size());
assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
cs.hideColumns(3, 6);
assertEquals(1, hidden.size());
assertSame(firstHiddenRange, cs.getHiddenColumns().get(0));
cs.revealAllHiddenColumns();
cs.hideColumns(2, 4);
hidden = cs.getHiddenColumns();
assertEquals(1, hidden.size());
assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
// extend contiguous with 2 positions overlap
cs.hideColumns(3, 5);
assertEquals(1, hidden.size());
assertEquals("[2, 5]", Arrays.toString(hidden.get(0)));
// extend contiguous with 1 position overlap
cs.hideColumns(5, 6);
assertEquals(1, hidden.size());
assertEquals("[2, 6]", Arrays.toString(hidden.get(0)));
// extend contiguous with overlap both ends:
cs.hideColumns(1, 7);
assertEquals(1, hidden.size());
assertEquals("[1, 7]", Arrays.toString(hidden.get(0)));
}
/**
* Test the method that hides a specified column including any adjacent
* selected columns. This is a convenience method for the case where multiple
* column regions are selected and then hidden using menu option View | Hide |
* Selected Columns.
*/
@Test(groups = { "Functional" })
public void testHideColumns_withSelection()
{
ColumnSelection cs = new ColumnSelection();
// select columns 4-6
cs.addElement(4);
cs.addElement(5);
cs.addElement(6);
// hide column 5 (and adjacent):
cs.hideColumns(5);
// 4,5,6 now hidden:
List hidden = cs.getHiddenColumns();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
// none now selected:
assertTrue(cs.getSelected().isEmpty());
// repeat, hiding column 4 (5 and 6)
cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(5);
cs.addElement(6);
cs.hideColumns(4);
hidden = cs.getHiddenColumns();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
// repeat, hiding column (4, 5 and) 6
cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(5);
cs.addElement(6);
cs.hideColumns(6);
hidden = cs.getHiddenColumns();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
// repeat, with _only_ adjacent columns selected
cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(6);
cs.hideColumns(5);
hidden = cs.getHiddenColumns();
assertEquals(1, hidden.size());
assertEquals("[4, 6]", Arrays.toString(hidden.get(0)));
assertTrue(cs.getSelected().isEmpty());
}
/**
* Test the method that hides all (possibly disjoint) selected column ranges
*/
@Test(groups = { "Functional" })
public void testHideSelectedColumns()
{
ColumnSelection cs = new ColumnSelection();
int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
for (int col : sel)
{
cs.addElement(col);
}
cs.hideColumns(15, 18);
cs.hideSelectedColumns();
assertTrue(cs.getSelected().isEmpty());
List hidden = cs.getHiddenColumns();
assertEquals(4, hidden.size());
assertEquals("[2, 4]", Arrays.toString(hidden.get(0)));
assertEquals("[7, 9]", Arrays.toString(hidden.get(1)));
assertEquals("[15, 18]", Arrays.toString(hidden.get(2)));
assertEquals("[20, 22]", Arrays.toString(hidden.get(3)));
}
/**
* Test the method that gets runs of selected columns ordered by column. If
* this fails, HideSelectedColumns may also fail
*/
@Test(groups = { "Functional" })
public void testgetSelectedRanges()
{
ColumnSelection cs = new ColumnSelection();
int[] sel = { 2, 3, 4, 7, 8, 9, 20, 21, 22 };
for (int col : sel)
{
cs.addElement(col);
}
List range;
range = cs.getSelectedRanges();
assertEquals(3, range.size());
assertEquals("[2, 4]", Arrays.toString(range.get(0)));
assertEquals("[7, 9]", Arrays.toString(range.get(1)));
assertEquals("[20, 22]", Arrays.toString(range.get(2)));
cs.addElement(0);
cs.addElement(1);
range = cs.getSelectedRanges();
assertEquals(3, range.size());
assertEquals("[0, 4]", Arrays.toString(range.get(0)));
}
/**
* Test the method that reveals a range of hidden columns given the start
* column of the range
*/
@Test(groups = { "Functional" })
public void testRevealHiddenColumns()
{
ColumnSelection cs = new ColumnSelection();
cs.hideColumns(5, 8);
cs.addElement(10);
cs.revealHiddenColumns(5);
// hidden columns list now null but getter returns empty list:
assertTrue(cs.getHiddenColumns().isEmpty());
// revealed columns are marked as selected (added to selection):
assertEquals("[10, 5, 6, 7, 8]", cs.getSelected().toString());
// calling with a column other than the range start does nothing:
cs = new ColumnSelection();
cs.hideColumns(5, 8);
List hidden = cs.getHiddenColumns();
cs.revealHiddenColumns(6);
assertSame(hidden, cs.getHiddenColumns());
assertTrue(cs.getSelected().isEmpty());
}
@Test(groups = { "Functional" })
public void testRevealAllHiddenColumns()
{
ColumnSelection cs = new ColumnSelection();
cs.hideColumns(5, 8);
cs.hideColumns(2, 3);
cs.addElement(11);
cs.addElement(1);
cs.revealAllHiddenColumns();
/*
* revealing hidden columns adds them (in order) to the (unordered)
* selection list
*/
assertTrue(cs.getHiddenColumns().isEmpty());
assertEquals("[11, 1, 2, 3, 5, 6, 7, 8]", cs.getSelected().toString());
}
@Test(groups = { "Functional" })
public void testIsVisible()
{
ColumnSelection cs = new ColumnSelection();
cs.hideColumns(2, 4);
cs.hideColumns(6, 7);
assertTrue(cs.isVisible(0));
assertTrue(cs.isVisible(-99));
assertTrue(cs.isVisible(1));
assertFalse(cs.isVisible(2));
assertFalse(cs.isVisible(3));
assertFalse(cs.isVisible(4));
assertTrue(cs.isVisible(5));
assertFalse(cs.isVisible(6));
assertFalse(cs.isVisible(7));
}
@Test(groups = { "Functional" })
public void testGetVisibleContigs()
{
ColumnSelection cs = new ColumnSelection();
cs.hideColumns(3, 6);
cs.hideColumns(8, 9);
cs.hideColumns(12, 12);
// start position is inclusive, end position exclusive:
int[] visible = cs.getVisibleContigs(1, 13);
assertEquals("[1, 2, 7, 7, 10, 11]", Arrays.toString(visible));
visible = cs.getVisibleContigs(4, 14);
assertEquals("[7, 7, 10, 11, 13, 13]", Arrays.toString(visible));
visible = cs.getVisibleContigs(3, 10);
assertEquals("[7, 7]", Arrays.toString(visible));
visible = cs.getVisibleContigs(4, 6);
assertEquals("[]", Arrays.toString(visible));
}
@Test(groups = { "Functional" })
public void testInvertColumnSelection()
{
ColumnSelection cs = new ColumnSelection();
cs.addElement(4);
cs.addElement(6);
cs.addElement(8);
cs.hideColumns(3, 3);
cs.hideColumns(6, 6);
// invert selection from start (inclusive) to end (exclusive)
// hidden columns are _not_ changed
cs.invertColumnSelection(2, 9);
assertEquals("[2, 5, 7]", cs.getSelected().toString());
cs.invertColumnSelection(1, 9);
assertEquals("[1, 4, 8]", cs.getSelected().toString());
}
@Test(groups = { "Functional" })
public void testMaxColumnSelection()
{
ColumnSelection cs = new ColumnSelection();
cs.addElement(0);
cs.addElement(513);
cs.addElement(1);
assertEquals(513, cs.getMax());
cs.removeElement(513);
assertEquals(1, cs.getMax());
cs.removeElement(1);
assertEquals(0, cs.getMax());
cs.addElement(512);
cs.addElement(513);
assertEquals(513, cs.getMax());
}
@Test(groups = { "Functional" })
public void testMinColumnSelection()
{
ColumnSelection cs = new ColumnSelection();
cs.addElement(0);
cs.addElement(513);
cs.addElement(1);
assertEquals(0, cs.getMin());
cs.removeElement(0);
assertEquals(1, cs.getMin());
cs.addElement(0);
assertEquals(0, cs.getMin());
}
@Test(groups = { "Functional" })
public void testEquals()
{
ColumnSelection cs = new ColumnSelection();
cs.addElement(0);
cs.addElement(513);
cs.addElement(1);
cs.hideColumns(3);
cs.hideColumns(7);
cs.hideColumns(5,9);
// same selections added in a different order
ColumnSelection cs2 = new ColumnSelection();
cs2.addElement(1);
cs2.addElement(513);
cs2.addElement(0);
// with no hidden columns
assertFalse(cs.equals(cs2));
assertFalse(cs2.equals(cs));
// with hidden columns added in a different order
cs2.hideColumns(6, 9);
cs2.hideColumns(5, 8);
cs2.hideColumns(3);
assertTrue(cs.equals(cs2));
assertTrue(cs.equals(cs));
assertTrue(cs2.equals(cs));
assertTrue(cs2.equals(cs2));
cs2.addElement(12);
assertFalse(cs.equals(cs2));
assertFalse(cs2.equals(cs));
cs2.removeElement(12);
assertTrue(cs.equals(cs2));
cs2.hideColumns(88);
assertFalse(cs.equals(cs2));
/*
* unhiding a column adds it to selection!
*/
cs2.revealHiddenColumns(88);
assertFalse(cs.equals(cs2));
cs.addElement(88);
assertTrue(cs.equals(cs2));
}
}