+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
package jalview.datamodel;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertSame;
+import static org.testng.AssertJUnit.assertTrue;
+import jalview.datamodel.PDBEntry.Type;
+
+import java.util.Arrays;
import java.util.List;
+import java.util.Vector;
-import org.junit.Before;
-import org.junit.Test;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
public class SequenceTest
{
SequenceI seq;
- @Before
+ @BeforeMethod(alwaysRun = true)
public void setUp()
{
seq = new Sequence("FER1", "AKPNGVL");
}
- @Test
+
+ @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<int[]> 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());
}
- @Test
+ @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 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]);
}
private AlignmentAnnotation addAnnotation(String label,
- String description, String calcId,
- float value)
+ String description, String calcId, float value)
{
- final AlignmentAnnotation annotation = new AlignmentAnnotation(label, description,
- value);
+ final AlignmentAnnotation annotation = new AlignmentAnnotation(label,
+ description, value);
annotation.setCalcId(calcId);
seq.addAlignmentAnnotation(annotation);
return annotation;
}
- @Test
+ @Test(groups = { "Functional" })
public void testGetAlignmentAnnotations_forCalcIdAndLabel()
{
AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
1f);
AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
1f);
- AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null,
- 1f);
- AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3",
- 1f);
+ AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null, 1f);
+ AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3", 1f);
List<AlignmentAnnotation> 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());
* setting the sequenceRef on the annotation. Adding the same annotation twice
* should be ignored.
*/
- @Test
+ @Test(groups = { "Functional" })
public void testAddAlignmentAnnotation()
{
assertNull(seq.getAnnotation());
assertEquals(2, anns.length);
assertSame(annotation, anns[0]);
assertSame(annotation2, anns[1]);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetStartGetEnd()
+ {
+ SequenceI sq = new Sequence("test", "ABCDEF");
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+
+ sq = new Sequence("test", "--AB-C-DEF--");
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+
+ sq = new Sequence("test", "----");
+ assertEquals(1, sq.getStart());
+ assertEquals(0, sq.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 sq = new Sequence("test", "ABCDEF");
+ assertEquals(0, sq.findIndex(0));
+ assertEquals(1, sq.findIndex(1));
+ assertEquals(5, sq.findIndex(5));
+ assertEquals(6, sq.findIndex(6));
+ assertEquals(6, sq.findIndex(9));
+
+ sq = new Sequence("test", "-A--B-C-D-E-F--");
+ assertEquals(2, sq.findIndex(1));
+ assertEquals(5, sq.findIndex(2));
+ assertEquals(7, sq.findIndex(3));
+
+ // before start returns 0
+ assertEquals(0, sq.findIndex(0));
+ assertEquals(0, sq.findIndex(-1));
+
+ // beyond end returns last residue column
+ assertEquals(13, sq.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 sq = new Sequence("test", "ABCDEF");
+ assertEquals(1, sq.findPosition(0));
+ assertEquals(6, sq.findPosition(5));
+ // assertEquals(-1, seq.findPosition(6)); // fails
+
+ sq = new Sequence("test", "AB-C-D--");
+ assertEquals(1, sq.findPosition(0));
+ assertEquals(2, sq.findPosition(1));
+ // gap position 'finds' residue to the right (not the left as per javadoc)
+ assertEquals(3, sq.findPosition(2));
+ assertEquals(3, sq.findPosition(3));
+ assertEquals(4, sq.findPosition(4));
+ assertEquals(4, sq.findPosition(5));
+ // returns 1 more than sequence length if off the end ?!?
+ assertEquals(5, sq.findPosition(6));
+ assertEquals(5, sq.findPosition(7));
+
+ sq = new Sequence("test", "--AB-C-DEF--");
+ assertEquals(1, sq.findPosition(0));
+ assertEquals(1, sq.findPosition(1));
+ assertEquals(1, sq.findPosition(2));
+ assertEquals(2, sq.findPosition(3));
+ assertEquals(3, sq.findPosition(4));
+ assertEquals(3, sq.findPosition(5));
+ assertEquals(4, sq.findPosition(6));
+ assertEquals(4, sq.findPosition(7));
+ assertEquals(5, sq.findPosition(8));
+ assertEquals(6, sq.findPosition(9));
+ assertEquals(7, sq.findPosition(10));
+ assertEquals(7, sq.findPosition(11));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testDeleteChars()
+ {
+ SequenceI sq = new Sequence("test", "ABCDEF");
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+ sq.deleteChars(2, 3);
+ assertEquals("ABDEF", sq.getSequenceAsString());
+ assertEquals(1, sq.getStart());
+ assertEquals(5, sq.getEnd());
+
+ sq = new Sequence("test", "ABCDEF");
+ sq.deleteChars(0, 2);
+ assertEquals("CDEF", sq.getSequenceAsString());
+ assertEquals(3, sq.getStart());
+ assertEquals(6, sq.getEnd());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testInsertCharAt()
+ {
+ // non-static methods:
+ SequenceI sq = new Sequence("test", "ABCDEF");
+ sq.insertCharAt(0, 'z');
+ assertEquals("zABCDEF", sq.getSequenceAsString());
+ sq.insertCharAt(2, 2, 'x');
+ assertEquals("zAxxBCDEF", sq.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 sq = new Sequence("test", "-A--B-CD-E--F-");
+ sq.createDatasetSequence();
+ assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(sq.gapMap()));
+ }
+
+ /**
+ * Test the method that gets sequence features, either from the sequence or
+ * its dataset.
+ */
+ @Test(groups = { "Functional" })
+ public void testGetSequenceFeatures()
+ {
+ SequenceI sq = new Sequence("test", "GATCAT");
+ sq.createDatasetSequence();
+
+ assertNull(sq.getSequenceFeatures());
+
+ /*
+ * SequenceFeature on sequence
+ */
+ SequenceFeature sf = new SequenceFeature();
+ sq.addSequenceFeature(sf);
+ SequenceFeature[] sfs = sq.getSequenceFeatures();
+ assertEquals(1, sfs.length);
+ assertSame(sf, sfs[0]);
+
+ /*
+ * SequenceFeature on sequence and dataset sequence; returns that on
+ * sequence
+ */
+ SequenceFeature sf2 = new SequenceFeature();
+ sq.getDatasetSequence().addSequenceFeature(sf2);
+ sfs = sq.getSequenceFeatures();
+ assertEquals(1, sfs.length);
+ assertSame(sf, sfs[0]);
+ /*
+ * SequenceFeature on dataset sequence only
+ */
+ sq.setSequenceFeatures(null);
+ sfs = sq.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.
+ */
+ sq.getDatasetSequence().setSequenceFeatures(null);
+ sq.getDatasetSequence().setDatasetSequence(sq); // loop!
+ assertNull(sq.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 sq = new Sequence("TestSeq", "AB.C-D E.");
+ int[] map = sq.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 sq = new Sequence("TestSeq", "ABCDEFG");
+ sq.createDatasetSequence();
+
+ // positions are base 0, end position is exclusive
+ SequenceI subseq = sq.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(sq.getDatasetSequence(), subseq.getDatasetSequence());
+ }
+
+ /**
+ * Test for deriveSequence applied to a sequence with a dataset
+ */
+ @Test(groups = { "Functional" })
+ public void testDeriveSequence_existingDataset()
+ {
+ SequenceI sq = new Sequence("Seq1", "CD");
+ sq.setDatasetSequence(new Sequence("Seq1", "ABCDEF"));
+ sq.getDatasetSequence().addSequenceFeature(
+ new SequenceFeature("", "", 1, 2, 0f, null));
+ sq.setStart(3);
+ sq.setEnd(4);
+ SequenceI derived = sq.deriveSequence();
+ assertEquals("CD", derived.getSequenceAsString());
+ assertSame(sq.getDatasetSequence(), derived.getDatasetSequence());
+
+ assertNull(((Sequence) seq).sequenceFeatures);
+ assertNull(((Sequence) derived).sequenceFeatures);
+ assertNotNull(seq.getSequenceFeatures());
+ assertSame(seq.getSequenceFeatures(), derived.getSequenceFeatures());
+ }
+
+ /**
+ * Test for deriveSequence applied to an ungapped sequence with no dataset
+ */
+ @Test(groups = { "Functional" })
+ public void testDeriveSequence_noDatasetUngapped()
+ {
+ SequenceI sq = new Sequence("Seq1", "ABCDEF");
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+ SequenceI derived = sq.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 sq = new Sequence("Seq1", "AB-C.D EF");
+ assertEquals(1, sq.getStart());
+ assertEquals(6, sq.getEnd());
+ assertNull(sq.getDatasetSequence());
+ SequenceI derived = sq.deriveSequence();
+ assertEquals("AB-C.D EF", derived.getSequenceAsString());
+ assertEquals("ABCDEF", derived.getDatasetSequence()
+ .getSequenceAsString());
+ }
+
+ @Test(groups = { "Functional" })
+ public void testCopyConstructor_noDataset()
+ {
+ SequenceI seq1 = new Sequence("Seq1", "AB-C.D EF");
+ seq1.setDescription("description");
+ seq1.addAlignmentAnnotation(new AlignmentAnnotation("label", "desc",
+ 1.3d));
+ seq1.addSequenceFeature(new SequenceFeature("type", "desc", 22, 33,
+ 12.4f, "group"));
+ seq1.addPDBId(new PDBEntry("1A70", "B", Type.PDB, "File"));
+ seq1.addDBRef(new DBRefEntry("EMBL", "1.2", "AZ12345"));
+
+ SequenceI copy = new Sequence(seq1);
+
+ assertNull(copy.getDatasetSequence());
+
+ verifyCopiedSequence(seq1, copy);
+
+ // copy has a copy of the DBRefEntry
+ // this is murky - DBrefs are only copied for dataset sequences
+ // where the test for 'dataset sequence' is 'dataset is null'
+ // but that doesn't distinguish it from an aligned sequence
+ // which has not yet generated a dataset sequence
+ // NB getDBRef looks inside dataset sequence if not null
+ DBRefEntry[] dbrefs = copy.getDBRefs();
+ assertEquals(1, dbrefs.length);
+ assertFalse(dbrefs[0] == seq1.getDBRefs()[0]);
+ assertTrue(dbrefs[0].equals(seq1.getDBRefs()[0]));
+ }
+
+ @Test(groups = { "Functional" })
+ public void testCopyConstructor_withDataset()
+ {
+ SequenceI seq1 = new Sequence("Seq1", "AB-C.D EF");
+ seq1.createDatasetSequence();
+ seq1.setDescription("description");
+ seq1.addAlignmentAnnotation(new AlignmentAnnotation("label", "desc",
+ 1.3d));
+ seq1.addSequenceFeature(new SequenceFeature("type", "desc", 22, 33,
+ 12.4f, "group"));
+ seq1.addPDBId(new PDBEntry("1A70", "B", Type.PDB, "File"));
+ // here we add DBRef to the dataset sequence:
+ seq1.getDatasetSequence().addDBRef(
+ new DBRefEntry("EMBL", "1.2", "AZ12345"));
+
+ SequenceI copy = new Sequence(seq1);
+
+ assertNotNull(copy.getDatasetSequence());
+ assertSame(copy.getDatasetSequence(), seq1.getDatasetSequence());
+
+ verifyCopiedSequence(seq1, copy);
+
+ // getDBRef looks inside dataset sequence and this is shared,
+ // so holds the same dbref objects
+ DBRefEntry[] dbrefs = copy.getDBRefs();
+ assertEquals(1, dbrefs.length);
+ assertSame(dbrefs[0], seq1.getDBRefs()[0]);
+ }
+
+ /**
+ * Helper to make assertions about a copied sequence
+ *
+ * @param seq1
+ * @param copy
+ */
+ protected void verifyCopiedSequence(SequenceI seq1, SequenceI copy)
+ {
+ // verify basic properties:
+ assertEquals(copy.getName(), seq1.getName());
+ assertEquals(copy.getDescription(), seq1.getDescription());
+ assertEquals(copy.getStart(), seq1.getStart());
+ assertEquals(copy.getEnd(), seq1.getEnd());
+ assertEquals(copy.getSequenceAsString(), seq1.getSequenceAsString());
+
+ // copy has a copy of the annotation:
+ AlignmentAnnotation[] anns = copy.getAnnotation();
+ assertEquals(1, anns.length);
+ assertFalse(anns[0] == seq1.getAnnotation()[0]);
+ assertEquals(anns[0].label, seq1.getAnnotation()[0].label);
+ assertEquals(anns[0].description, seq1.getAnnotation()[0].description);
+ assertEquals(anns[0].score, seq1.getAnnotation()[0].score);
+
+ // copy has a copy of the sequence feature:
+ SequenceFeature[] sfs = copy.getSequenceFeatures();
+ assertEquals(1, sfs.length);
+ assertFalse(sfs[0] == seq1.getSequenceFeatures()[0]);
+ assertTrue(sfs[0].equals(seq1.getSequenceFeatures()[0]));
+
+ // copy has a copy of the PDB entry
+ Vector<PDBEntry> pdbs = copy.getAllPDBEntries();
+ assertEquals(1, pdbs.size());
+ assertFalse(pdbs.get(0) == seq1.getAllPDBEntries().get(0));
+ assertTrue(pdbs.get(0).equals(seq1.getAllPDBEntries().get(0)));
+ }
+
+ @Test(groups = "Functional")
+ public void testGetCharAt()
+ {
+ SequenceI sq = new Sequence("", "abcde");
+ assertEquals('a', sq.getCharAt(0));
+ assertEquals('e', sq.getCharAt(4));
+ assertEquals(' ', sq.getCharAt(5));
+ assertEquals(' ', sq.getCharAt(-1));
}
}