package jalview.datamodel; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertSame; import static org.testng.AssertJUnit.assertTrue; import java.util.Arrays; import java.util.List; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; public class SequenceTest { SequenceI seq; @BeforeMethod public void setUp() { seq = new Sequence("FER1", "AKPNGVL"); } @Test(groups ={ "Functional" }) public void testInsertGapsAndGapmaps() { SequenceI aseq = seq.deriveSequence(); aseq.insertCharAt(2, 3, '-'); aseq.insertCharAt(6, 3, '-'); assertEquals("Gap insertions not correct", "AK---P---NGVL", aseq.getSequenceAsString()); List gapInt = aseq.getInsertions(); assertEquals("Gap interval 1 start wrong", 2, gapInt.get(0)[0]); assertEquals("Gap interval 1 end wrong", 4, gapInt.get(0)[1]); assertEquals("Gap interval 2 start wrong", 6, gapInt.get(1)[0]); assertEquals("Gap interval 2 end wrong", 8, gapInt.get(1)[1]); } @Test(groups ={ "Functional" }) public void testGetAnnotation() { // initial state returns null not an empty array assertNull(seq.getAnnotation()); AlignmentAnnotation ann = addAnnotation("label1", "desc1", "calcId1", 1f); AlignmentAnnotation[] anns = seq.getAnnotation(); assertEquals(1, anns.length); assertSame(ann, anns[0]); // removing all annotations reverts array to null seq.removeAlignmentAnnotation(ann); assertNull(seq.getAnnotation()); } @Test(groups ={ "Functional" }) public void testGetAnnotation_forLabel() { AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1", 1f); AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2", 1f); AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3", 1f); AlignmentAnnotation[] anns = seq.getAnnotation("label1"); assertEquals(2, anns.length); assertSame(ann1, anns[0]); assertSame(ann3, anns[1]); } private AlignmentAnnotation addAnnotation(String label, String description, String calcId, float value) { final AlignmentAnnotation annotation = new AlignmentAnnotation(label, description, value); annotation.setCalcId(calcId); seq.addAlignmentAnnotation(annotation); return annotation; } @Test(groups ={ "Functional" }) public void testGetAlignmentAnnotations_forCalcIdAndLabel() { AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1", 1f); AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2", 1f); AlignmentAnnotation ann3 = 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); List anns = seq.getAlignmentAnnotations("calcId2", "label2"); assertEquals(2, anns.size()); assertSame(ann2, anns.get(0)); assertSame(ann4, anns.get(1)); assertTrue(seq.getAlignmentAnnotations("calcId2", "label3").isEmpty()); assertTrue(seq.getAlignmentAnnotations("calcId3", "label5").isEmpty()); assertTrue(seq.getAlignmentAnnotations("calcId2", null).isEmpty()); assertTrue(seq.getAlignmentAnnotations(null, "label3").isEmpty()); assertTrue(seq.getAlignmentAnnotations(null, null).isEmpty()); } /** * Tests for addAlignmentAnnotation. Note this method has the side-effect of * setting the sequenceRef on the annotation. Adding the same annotation twice * should be ignored. */ @Test(groups ={ "Functional" }) public void testAddAlignmentAnnotation() { assertNull(seq.getAnnotation()); final AlignmentAnnotation annotation = new AlignmentAnnotation("a", "b", 2d); assertNull(annotation.sequenceRef); seq.addAlignmentAnnotation(annotation); assertSame(seq, annotation.sequenceRef); AlignmentAnnotation[] anns = seq.getAnnotation(); assertEquals(1, anns.length); assertSame(annotation, anns[0]); // re-adding does nothing seq.addAlignmentAnnotation(annotation); anns = seq.getAnnotation(); assertEquals(1, anns.length); assertSame(annotation, anns[0]); // an identical but different annotation can be added final AlignmentAnnotation annotation2 = new AlignmentAnnotation("a", "b", 2d); seq.addAlignmentAnnotation(annotation2); anns = seq.getAnnotation(); assertEquals(2, anns.length); assertSame(annotation, anns[0]); assertSame(annotation2, anns[1]); } @Test(groups ={ "Functional" }) public void testGetStartGetEnd() { SequenceI seq = new Sequence("test", "ABCDEF"); assertEquals(1, seq.getStart()); assertEquals(6, seq.getEnd()); seq = new Sequence("test", "--AB-C-DEF--"); assertEquals(1, seq.getStart()); assertEquals(6, seq.getEnd()); seq = new Sequence("test", "----"); assertEquals(1, seq.getStart()); assertEquals(0, seq.getEnd()); // ?? } /** * Tests for the method that returns an alignment column position (base 1) for * a given sequence position (base 1). */ @Test(groups ={ "Functional" }) public void testFindIndex() { SequenceI seq = new Sequence("test", "ABCDEF"); assertEquals(0, seq.findIndex(0)); assertEquals(1, seq.findIndex(1)); assertEquals(5, seq.findIndex(5)); assertEquals(6, seq.findIndex(6)); assertEquals(6, seq.findIndex(9)); seq = new Sequence("test", "-A--B-C-D-E-F--"); assertEquals(2, seq.findIndex(1)); assertEquals(5, seq.findIndex(2)); assertEquals(7, seq.findIndex(3)); // before start returns 0 assertEquals(0, seq.findIndex(0)); assertEquals(0, seq.findIndex(-1)); // beyond end returns last residue column assertEquals(13, seq.findIndex(99)); } /** * Tests for the method that returns a dataset sequence position (base 1) for * an aligned column position (base 0). */ @Test(groups ={ "Functional" }) public void testFindPosition() { SequenceI seq = new Sequence("test", "ABCDEF"); assertEquals(1, seq.findPosition(0)); assertEquals(6, seq.findPosition(5)); // assertEquals(-1, seq.findPosition(6)); // fails seq = new Sequence("test", "AB-C-D--"); assertEquals(1, seq.findPosition(0)); assertEquals(2, seq.findPosition(1)); // gap position 'finds' residue to the right (not the left as per javadoc) assertEquals(3, seq.findPosition(2)); assertEquals(3, seq.findPosition(3)); assertEquals(4, seq.findPosition(4)); assertEquals(4, seq.findPosition(5)); // returns 1 more than sequence length if off the end ?!? assertEquals(5, seq.findPosition(6)); assertEquals(5, seq.findPosition(7)); seq = new Sequence("test", "--AB-C-DEF--"); assertEquals(1, seq.findPosition(0)); assertEquals(1, seq.findPosition(1)); assertEquals(1, seq.findPosition(2)); assertEquals(2, seq.findPosition(3)); assertEquals(3, seq.findPosition(4)); assertEquals(3, seq.findPosition(5)); assertEquals(4, seq.findPosition(6)); assertEquals(4, seq.findPosition(7)); assertEquals(5, seq.findPosition(8)); assertEquals(6, seq.findPosition(9)); assertEquals(7, seq.findPosition(10)); assertEquals(7, seq.findPosition(11)); } @Test(groups ={ "Functional" }) public void testDeleteChars() { SequenceI seq = new Sequence("test", "ABCDEF"); assertEquals(1, seq.getStart()); assertEquals(6, seq.getEnd()); seq.deleteChars(2, 3); assertEquals("ABDEF", seq.getSequenceAsString()); assertEquals(1, seq.getStart()); assertEquals(5, seq.getEnd()); seq = new Sequence("test", "ABCDEF"); seq.deleteChars(0, 2); assertEquals("CDEF", seq.getSequenceAsString()); assertEquals(3, seq.getStart()); assertEquals(6, seq.getEnd()); } @Test(groups ={ "Functional" }) public void testInsertCharAt() { // non-static methods: SequenceI seq = new Sequence("test", "ABCDEF"); seq.insertCharAt(0, 'z'); assertEquals("zABCDEF", seq.getSequenceAsString()); seq.insertCharAt(2, 2, 'x'); assertEquals("zAxxBCDEF", seq.getSequenceAsString()); // for static method see StringUtilsTest } /** * Test the method that returns an array of aligned sequence positions where * the array index is the data sequence position (both base 0). */ @Test(groups ={ "Functional" }) public void testGapMap() { SequenceI seq = new Sequence("test", "-A--B-CD-E--F-"); seq.createDatasetSequence(); assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(seq.gapMap())); } /** * Test the method that gets sequence features, either from the sequence or * its dataset. */ @Test(groups ={ "Functional" }) public void testGetSequenceFeatures() { SequenceI seq = new Sequence("test", "GATCAT"); seq.createDatasetSequence(); assertNull(seq.getSequenceFeatures()); /* * SequenceFeature on sequence */ SequenceFeature sf = new SequenceFeature(); seq.addSequenceFeature(sf); SequenceFeature[] sfs = seq.getSequenceFeatures(); assertEquals(1, sfs.length); assertSame(sf, sfs[0]); /* * SequenceFeature on sequence and dataset sequence; returns that on * sequence */ SequenceFeature sf2 = new SequenceFeature(); seq.getDatasetSequence().addSequenceFeature(sf2); sfs = seq.getSequenceFeatures(); assertEquals(1, sfs.length); assertSame(sf, sfs[0]); /* * SequenceFeature on dataset sequence only */ seq.setSequenceFeatures(null); sfs = seq.getSequenceFeatures(); assertEquals(1, sfs.length); assertSame(sf2, sfs[0]); /* * Corrupt case - no SequenceFeature, dataset's dataset is the original * sequence. Test shows no infinite loop results. */ seq.getDatasetSequence().setSequenceFeatures(null); seq.getDatasetSequence().setDatasetSequence(seq); // loop! assertNull(seq.getSequenceFeatures()); } /** * Test the method that returns an array, indexed by sequence position, whose * entries are the residue positions at the sequence position (or to the right * if a gap) */ @Test(groups ={ "Functional" }) public void testFindPositionMap() { /* * Note: Javadoc for findPosition says it returns the residue position to * the left of a gapped position; in fact it returns the position to the * right. Also it returns a non-existent residue position for a gap beyond * the sequence. */ Sequence seq = new Sequence("TestSeq", "AB.C-D E."); int[] map = seq.findPositionMap(); assertEquals(Arrays.toString(new int[] { 1, 2, 3, 3, 4, 4, 5, 5, 6 }), Arrays.toString(map)); } /** * Test for getSubsequence */ @Test(groups ={ "Functional" }) public void testGetSubsequence() { SequenceI seq = new Sequence("TestSeq", "ABCDEFG"); seq.createDatasetSequence(); // positions are base 0, end position is exclusive SequenceI subseq = seq.getSubSequence(2, 4); assertEquals("CD", subseq.getSequenceAsString()); // start/end are base 1 positions assertEquals(3, subseq.getStart()); assertEquals(4, subseq.getEnd()); // subsequence shares the full dataset sequence assertSame(seq.getDatasetSequence(), subseq.getDatasetSequence()); } /** * Test for deriveSequence applied to a sequence with a dataset */ @Test(groups ={ "Functional" }) public void testDeriveSequence_existingDataset() { SequenceI seq = new Sequence("Seq1", "CD"); seq.setDatasetSequence(new Sequence("Seq1", "ABCDEF")); seq.setStart(3); seq.setEnd(4); SequenceI derived = seq.deriveSequence(); assertEquals("CD", derived.getSequenceAsString()); assertSame(seq.getDatasetSequence(), derived.getDatasetSequence()); } /** * Test for deriveSequence applied to an ungapped sequence with no dataset */ @Test(groups ={ "Functional" }) public void testDeriveSequence_noDatasetUngapped() { SequenceI seq = new Sequence("Seq1", "ABCDEF"); assertEquals(1, seq.getStart()); assertEquals(6, seq.getEnd()); SequenceI derived = seq.deriveSequence(); assertEquals("ABCDEF", derived.getSequenceAsString()); assertEquals("ABCDEF", derived.getDatasetSequence() .getSequenceAsString()); } /** * Test for deriveSequence applied to a gapped sequence with no dataset */ @Test(groups ={ "Functional" }) public void testDeriveSequence_noDatasetGapped() { SequenceI seq = new Sequence("Seq1", "AB-C.D EF"); assertEquals(1, seq.getStart()); assertEquals(6, seq.getEnd()); assertNull(seq.getDatasetSequence()); SequenceI derived = seq.deriveSequence(); assertEquals("AB-C.D EF", derived.getSequenceAsString()); assertEquals("ABCDEF", derived.getDatasetSequence() .getSequenceAsString()); } }