X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=test%2Fjalview%2Fdatamodel%2FSequenceTest.java;h=6d071130c23182cb703dcbad0734ee6ed6b3074b;hb=0bf5983f8a17fdfecb2cac649e3650763a8973ce;hp=4f429477eae8a173c5e750024cc0e6a8a946b01a;hpb=70a93ebbabd80e25c60a0e6444013ed4260b09a5;p=jalview.git diff --git a/test/jalview/datamodel/SequenceTest.java b/test/jalview/datamodel/SequenceTest.java index 4f42947..6d07113 100644 --- a/test/jalview/datamodel/SequenceTest.java +++ b/test/jalview/datamodel/SequenceTest.java @@ -28,28 +28,31 @@ import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertSame; import static org.testng.AssertJUnit.assertTrue; +import jalview.analysis.AlignmentGenerator; import jalview.commands.EditCommand; import jalview.commands.EditCommand.Action; import jalview.datamodel.PDBEntry.Type; import jalview.gui.JvOptionPane; import jalview.util.MapList; +import jalview.ws.params.InvalidArgumentException; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.BitSet; +import java.util.Iterator; import java.util.List; import java.util.Vector; -import junit.extensions.PA; - import org.testng.Assert; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; +import junit.extensions.PA; + public class SequenceTest { - @BeforeClass(alwaysRun = true) public void setUpJvOptionPane() { @@ -78,6 +81,18 @@ public class SequenceTest 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]); + + BitSet gapfield = aseq.getInsertionsAsBits(); + BitSet expectedgaps = new BitSet(); + expectedgaps.set(2, 5); + expectedgaps.set(6, 9); + + assertEquals(6, expectedgaps.cardinality()); + + assertEquals("getInsertionsAsBits didn't mark expected number of gaps", + 6, gapfield.cardinality()); + + assertEquals("getInsertionsAsBits not correct.", expectedgaps, gapfield); } @Test(groups = ("Functional")) @@ -93,15 +108,23 @@ public class SequenceTest // change sequence, should trigger an update of cached result sq.setSequence("ASDFASDFADSF"); assertTrue(sq.isProtein()); - /* - * in situ change of sequence doesn't change hashcode :-O - * (sequence should not expose internal implementation) - */ - for (int i = 0; i < sq.getSequence().length; i++) - { - sq.getSequence()[i] = "acgtu".charAt(i % 5); - } - assertTrue(sq.isProtein()); // but it isn't + } + + @Test(groups = ("Functional")) + public void testIsProteinWithXorNAmbiguityCodes() + { + // test Protein with N - poly asparagine + assertTrue(new Sequence("prot", "ASDFASDFASDFNNNNNNNNN").isProtein()); + assertTrue(new Sequence("prot", "NNNNNNNNNNNNNNNNNNNNN").isProtein()); + // test Protein with X + assertTrue(new Sequence("prot", "ASDFASDFASDFXXXXXXXXX").isProtein()); + // test DNA with X + assertFalse(new Sequence("prot", "ACGTACGTACGTXXXXXXXX").isProtein()); + // test DNA with N + assertFalse(new Sequence("prot", "ACGTACGTACGTNNNNNNNN").isProtein()); + // test RNA with X + assertFalse(new Sequence("prot", "ACGUACGUACGUXXXXXXXXX").isProtein()); + assertFalse(new Sequence("prot", "ACGUACGUACGUNNNNNNNNN").isProtein()); } @Test(groups = { "Functional" }) @@ -241,7 +264,9 @@ public class SequenceTest sq.sequenceChanged(); assertEquals(6, sq.findIndex(9)); - sq = new Sequence("test/8-13", "-A--B-C-D-E-F--"); + final String aligned = "-A--B-C-D-E-F--"; + assertEquals(15, aligned.length()); + sq = new Sequence("test/8-13", aligned); assertEquals(2, sq.findIndex(8)); sq.sequenceChanged(); assertEquals(5, sq.findIndex(9)); @@ -257,6 +282,84 @@ public class SequenceTest // beyond end returns last residue column sq.sequenceChanged(); assertEquals(13, sq.findIndex(99)); + + /* + * residue before sequence 'end' but beyond end of sequence returns + * length of sequence (last column) (rightly or wrongly!) + */ + sq = new Sequence("test/8-15", "A-B-C-"); // trailing gap case + assertEquals(6, sq.getLength()); + sq.sequenceChanged(); + assertEquals(sq.getLength(), sq.findIndex(14)); + sq = new Sequence("test/8-99", "-A--B-C-D"); // trailing residue case + sq.sequenceChanged(); + assertEquals(sq.getLength(), sq.findIndex(65)); + + /* + * residue after sequence 'start' but before first residue returns + * zero (before first column) (rightly or wrongly!) + */ + sq = new Sequence("test/8-15", "-A-B-C-"); // leading gap case + sq.sequenceChanged(); + assertEquals(0, sq.findIndex(3)); + sq = new Sequence("test/8-15", "A-B-C-"); // leading residue case + sq.sequenceChanged(); + assertEquals(0, sq.findIndex(2)); + } + + @Test(groups = { "Functional" }) + public void testFindPositions() + { + SequenceI sq = new Sequence("test/8-13", "-ABC---DE-F--"); + + /* + * invalid inputs + */ + assertNull(sq.findPositions(6, 5)); + assertNull(sq.findPositions(0, 5)); + assertNull(sq.findPositions(-1, 5)); + + /* + * all gapped ranges + */ + assertNull(sq.findPositions(1, 1)); // 1-based columns + assertNull(sq.findPositions(5, 5)); + assertNull(sq.findPositions(5, 6)); + assertNull(sq.findPositions(5, 7)); + + /* + * all ungapped ranges + */ + assertEquals(new Range(8, 8), sq.findPositions(2, 2)); // A + assertEquals(new Range(8, 9), sq.findPositions(2, 3)); // AB + assertEquals(new Range(8, 10), sq.findPositions(2, 4)); // ABC + assertEquals(new Range(9, 10), sq.findPositions(3, 4)); // BC + + /* + * gap to ungapped range + */ + assertEquals(new Range(8, 10), sq.findPositions(1, 4)); // ABC + assertEquals(new Range(11, 12), sq.findPositions(6, 9)); // DE + + /* + * ungapped to gapped range + */ + assertEquals(new Range(10, 10), sq.findPositions(4, 5)); // C + assertEquals(new Range(9, 13), sq.findPositions(3, 11)); // BCDEF + + /* + * ungapped to ungapped enclosing gaps + */ + assertEquals(new Range(10, 11), sq.findPositions(4, 8)); // CD + assertEquals(new Range(8, 13), sq.findPositions(2, 11)); // ABCDEF + + /* + * gapped to gapped enclosing ungapped + */ + assertEquals(new Range(8, 10), sq.findPositions(1, 5)); // ABC + assertEquals(new Range(11, 12), sq.findPositions(5, 10)); // DE + assertEquals(new Range(8, 13), sq.findPositions(1, 13)); // the lot + assertEquals(new Range(8, 13), sq.findPositions(1, 99)); } /** @@ -273,6 +376,8 @@ public class SequenceTest SequenceI sq = new Sequence("test/8-13", "ABCDEF"); assertEquals(8, sq.findPosition(0)); // Sequence should now hold a cursor at [8, 0] + assertEquals("test:Pos8:Col1:startCol1:endCol0:tok1", + PA.getValue(sq, "cursor").toString()); SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor"); int token = (int) PA.getValue(sq, "changeCount"); assertEquals(new SequenceCursor(sq, 8, 1, token), cursor); @@ -281,24 +386,31 @@ public class SequenceTest /* * find F13 at column offset 5, cursor should update to [13, 6] + * endColumn is found and saved in cursor */ assertEquals(13, sq.findPosition(5)); cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(++token, (int) PA.getValue(sq, "changeCount")); assertEquals(new SequenceCursor(sq, 13, 6, token), cursor); + assertEquals("test:Pos13:Col6:startCol1:endCol6:tok2", + PA.getValue(sq, "cursor").toString()); // assertEquals(-1, seq.findPosition(6)); // fails sq = new Sequence("test/8-11", "AB-C-D--"); - token = (int) PA.getValue(sq, "changeCount"); // 0 + token = (int) PA.getValue(sq, "changeCount"); // 1 for setStart assertEquals(8, sq.findPosition(0)); cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 8, 1, token), cursor); + assertEquals("test:Pos8:Col1:startCol1:endCol0:tok1", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(9, sq.findPosition(1)); cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 9, 2, ++token), cursor); + assertEquals("test:Pos9:Col2:startCol1:endCol0:tok2", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); // gap position 'finds' residue to the right (not the left as per javadoc) @@ -306,11 +418,15 @@ public class SequenceTest assertEquals(10, sq.findPosition(2)); cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 9, 2, ++token), cursor); + assertEquals("test:Pos9:Col2:startCol1:endCol0:tok3", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(10, sq.findPosition(3)); cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 10, 4, ++token), cursor); + assertEquals("test:Pos10:Col4:startCol1:endCol0:tok4", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); // column[4] is the gap after C - returns D11 @@ -318,11 +434,16 @@ public class SequenceTest assertEquals(11, sq.findPosition(4)); cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 10, 4, ++token), cursor); + assertEquals("test:Pos10:Col4:startCol1:endCol0:tok5", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(11, sq.findPosition(5)); // D cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 11, 6, ++token), cursor); + // lastCol has been found and saved in the cursor + assertEquals("test:Pos11:Col6:startCol1:endCol6:tok6", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); // returns 1 more than sequence length if off the end ?!? @@ -331,38 +452,69 @@ public class SequenceTest sq.sequenceChanged(); assertEquals(12, sq.findPosition(7)); + /* + * first findPosition should also set firstResCol in cursor + */ sq = new Sequence("test/8-13", "--AB-C-DEF--"); assertEquals(8, sq.findPosition(0)); + assertNull(PA.getValue(sq, "cursor")); + assertEquals(1, PA.getValue(sq, "changeCount")); sq.sequenceChanged(); assertEquals(8, sq.findPosition(1)); + assertNull(PA.getValue(sq, "cursor")); sq.sequenceChanged(); assertEquals(8, sq.findPosition(2)); + assertEquals("test:Pos8:Col3:startCol3:endCol0:tok3", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(9, sq.findPosition(3)); + assertEquals("test:Pos9:Col4:startCol3:endCol0:tok4", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); + // column[4] is a gap, returns next residue pos (C10) + // cursor is set to last residue found [B] assertEquals(10, sq.findPosition(4)); + assertEquals("test:Pos9:Col4:startCol3:endCol0:tok5", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(10, sq.findPosition(5)); + assertEquals("test:Pos10:Col6:startCol3:endCol0:tok6", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); + // column[6] is a gap, returns next residue pos (D11) + // cursor is set to last residue found [C] assertEquals(11, sq.findPosition(6)); + assertEquals("test:Pos10:Col6:startCol3:endCol0:tok7", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(11, sq.findPosition(7)); + assertEquals("test:Pos11:Col8:startCol3:endCol0:tok8", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(12, sq.findPosition(8)); + assertEquals("test:Pos12:Col9:startCol3:endCol0:tok9", + PA.getValue(sq, "cursor").toString()); + /* + * when the last residue column is found, it is set in the cursor + */ sq.sequenceChanged(); assertEquals(13, sq.findPosition(9)); + assertEquals("test:Pos13:Col10:startCol3:endCol10:tok10", + PA.getValue(sq, "cursor").toString()); sq.sequenceChanged(); assertEquals(14, sq.findPosition(10)); + assertEquals("test:Pos13:Col10:startCol3:endCol10:tok11", + PA.getValue(sq, "cursor").toString()); /* * findPosition for column beyond sequence length @@ -370,8 +522,33 @@ public class SequenceTest */ sq.sequenceChanged(); assertEquals(14, sq.findPosition(11)); + assertEquals("test:Pos13:Col10:startCol3:endCol10:tok12", + PA.getValue(sq, "cursor").toString()); + sq.sequenceChanged(); assertEquals(14, sq.findPosition(99)); + assertEquals("test:Pos13:Col10:startCol3:endCol10:tok13", + PA.getValue(sq, "cursor").toString()); + + /* + * gapped sequence ending in non-gap + */ + sq = new Sequence("test/8-13", "--AB-C-DEF"); + assertEquals(13, sq.findPosition(9)); + assertEquals("test:Pos13:Col10:startCol3:endCol10:tok1", + PA.getValue(sq, "cursor").toString()); + sq.sequenceChanged(); + assertEquals(12, sq.findPosition(8)); // E12 + // sequenceChanged() invalidates cursor.lastResidueColumn + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals("test:Pos12:Col9:startCol3:endCol0:tok2", + cursor.toString()); + // findPosition with cursor accepts base 1 column values + assertEquals(13, ((Sequence) sq).findPosition(10, cursor)); + assertEquals(13, sq.findPosition(9)); // F13 + // lastResidueColumn has now been found and saved in cursor + assertEquals("test:Pos13:Col10:startCol3:endCol10:tok2", + PA.getValue(sq, "cursor").toString()); } @Test(groups = { "Functional" }) @@ -400,6 +577,13 @@ public class SequenceTest assertEquals(6, sq.getEnd()); assertNull(PA.getValue(sq, "datasetSequence")); + sq = new Sequence("test", "ABCDE"); + sq.deleteChars(0, 3); + assertEquals("DE", sq.getSequenceAsString()); + assertEquals(4, sq.getStart()); + assertEquals(5, sq.getEnd()); + assertNull(PA.getValue(sq, "datasetSequence")); + /* * delete at end */ @@ -409,6 +593,21 @@ public class SequenceTest assertEquals(1, sq.getStart()); assertEquals(4, sq.getEnd()); assertNull(PA.getValue(sq, "datasetSequence")); + + /* + * delete more positions than there are + */ + sq = new Sequence("test/8-11", "ABCD"); + sq.deleteChars(0, 99); + assertEquals("", sq.getSequenceAsString()); + assertEquals(12, sq.getStart()); // = findPosition(99) ?!? + assertEquals(11, sq.getEnd()); + + sq = new Sequence("test/8-11", "----"); + sq.deleteChars(0, 99); // ArrayIndexOutOfBoundsException <= 2.10.2 + assertEquals("", sq.getSequenceAsString()); + assertEquals(8, sq.getStart()); + assertEquals(11, sq.getEnd()); } @Test(groups = { "Functional" }) @@ -434,9 +633,9 @@ public class SequenceTest assertNotNull(newDs); assertNotSame(ds, newDs); assertNotNull(sq.getDBRefs()); - assertEquals(1, sq.getDBRefs().length); - assertNotSame(dbr1, sq.getDBRefs()[0]); - assertEquals(dbr1, sq.getDBRefs()[0]); + assertEquals(1, sq.getDBRefs().size()); + assertNotSame(dbr1, sq.getDBRefs().get(0)); + assertEquals(dbr1, sq.getDBRefs().get(0)); /* * internal delete with sequence features @@ -497,8 +696,8 @@ public class SequenceTest assertEquals(4, sq.getEnd()); assertSame(ds, PA.getValue(sq, "datasetSequence")); assertNotNull(sq.getDBRefs()); - assertEquals(1, sq.getDBRefs().length); - assertSame(dbr1, sq.getDBRefs()[0]); + assertEquals(1, sq.getDBRefs().size()); + assertSame(dbr1, sq.getDBRefs().get(0)); } @Test(groups = { "Functional" }) @@ -721,7 +920,7 @@ public class SequenceTest Assert.assertEquals(pdbe1a, sq.getDatasetSequence().getPDBEntry("1PDB"), "PDB Entry '1PDB' not found on dataset sequence via getPDBEntry."); - ArrayList annotsList = new ArrayList(); + ArrayList annotsList = new ArrayList<>(); System.out.println(">>>>>> " + sq.getSequenceAsString().length()); annotsList.add(new Annotation("A", "A", 'X', 0.1f)); annotsList.add(new Annotation("A", "A", 'X', 0.1f)); @@ -732,12 +931,12 @@ public class SequenceTest new AlignmentAnnotation("Test annot", "Test annot description", annots)); Assert.assertEquals(sq.getDescription(), "Test sequence description.."); - Assert.assertEquals(sq.getDBRefs().length, 5); // DBRefs are on dataset + Assert.assertEquals(sq.getDBRefs().size(), 5); // DBRefs are on dataset // sequence Assert.assertEquals(sq.getAllPDBEntries().size(), 4); Assert.assertNotNull(sq.getAnnotation()); Assert.assertEquals(sq.getAnnotation()[0].annotations.length, 2); - Assert.assertEquals(sq.getDatasetSequence().getDBRefs().length, 5); // same + Assert.assertEquals(sq.getDatasetSequence().getDBRefs().size(), 5); // same // as // sq.getDBRefs() Assert.assertEquals(sq.getDatasetSequence().getAllPDBEntries().size(), @@ -748,11 +947,11 @@ public class SequenceTest Assert.assertEquals(derived.getDescription(), "Test sequence description.."); - Assert.assertEquals(derived.getDBRefs().length, 5); // come from dataset + Assert.assertEquals(derived.getDBRefs().size(), 5); // come from dataset Assert.assertEquals(derived.getAllPDBEntries().size(), 4); Assert.assertNotNull(derived.getAnnotation()); Assert.assertEquals(derived.getAnnotation()[0].annotations.length, 2); - Assert.assertEquals(derived.getDatasetSequence().getDBRefs().length, 5); + Assert.assertEquals(derived.getDatasetSequence().getDBRefs().size(), 5); Assert.assertEquals(derived.getDatasetSequence().getAllPDBEntries() .size(), 4); Assert.assertNotNull(derived.getDatasetSequence().getAnnotation()); @@ -831,10 +1030,10 @@ public class SequenceTest // 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])); + List dbrefs = copy.getDBRefs(); + assertEquals(1, dbrefs.size()); + assertFalse(dbrefs.get(0) == seq1.getDBRefs().get(0)); + assertTrue(dbrefs.get(0).equals(seq1.getDBRefs().get(0))); } @Test(groups = { "Functional" }) @@ -863,9 +1062,9 @@ public class SequenceTest // 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]); + List dbrefs = copy.getDBRefs(); + assertEquals(1, dbrefs.size()); + assertSame(dbrefs.get(0), seq1.getDBRefs().get(0)); } /** @@ -964,39 +1163,39 @@ public class SequenceTest assertNull(sq.getDBRefs()); DBRefEntry dbref = new DBRefEntry("Uniprot", "1", "P00340"); sq.addDBRef(dbref); - assertEquals(1, sq.getDBRefs().length); - assertSame(dbref, sq.getDBRefs()[0]); + assertEquals(1, sq.getDBRefs().size()); + assertSame(dbref, sq.getDBRefs().get(0)); /* * change of version - new entry */ DBRefEntry dbref2 = new DBRefEntry("Uniprot", "2", "P00340"); sq.addDBRef(dbref2); - assertEquals(2, sq.getDBRefs().length); - assertSame(dbref, sq.getDBRefs()[0]); - assertSame(dbref2, sq.getDBRefs()[1]); + assertEquals(2, sq.getDBRefs().size()); + assertSame(dbref, sq.getDBRefs().get(0)); + assertSame(dbref2, sq.getDBRefs().get(1)); /* * matches existing entry - not added */ sq.addDBRef(new DBRefEntry("UNIPROT", "1", "p00340")); - assertEquals(2, sq.getDBRefs().length); + assertEquals(2, sq.getDBRefs().size()); /* * different source = new entry */ DBRefEntry dbref3 = new DBRefEntry("UniRef", "1", "p00340"); sq.addDBRef(dbref3); - assertEquals(3, sq.getDBRefs().length); - assertSame(dbref3, sq.getDBRefs()[2]); + assertEquals(3, sq.getDBRefs().size()); + assertSame(dbref3, sq.getDBRefs().get(2)); /* * different ref = new entry */ DBRefEntry dbref4 = new DBRefEntry("UniRef", "1", "p00341"); sq.addDBRef(dbref4); - assertEquals(4, sq.getDBRefs().length); - assertSame(dbref4, sq.getDBRefs()[3]); + assertEquals(4, sq.getDBRefs().size()); + assertSame(dbref4, sq.getDBRefs().get(3)); /* * matching ref with a mapping - map updated @@ -1006,8 +1205,8 @@ public class SequenceTest 1, 1 }, 3, 1)); dbref5.setMap(map); sq.addDBRef(dbref5); - assertEquals(4, sq.getDBRefs().length); - assertSame(dbref4, sq.getDBRefs()[3]); + assertEquals(4, sq.getDBRefs().size()); + assertSame(dbref4, sq.getDBRefs().get(3)); assertSame(map, dbref4.getMap()); /* @@ -1017,8 +1216,8 @@ public class SequenceTest DBRefEntry dbref6 = new DBRefEntry(dbref2.getSource(), "3", dbref2.getAccessionId()); sq.addDBRef(dbref6); - assertEquals(4, sq.getDBRefs().length); - assertSame(dbref2, sq.getDBRefs()[1]); + assertEquals(4, sq.getDBRefs().size()); + assertSame(dbref2, sq.getDBRefs().get(1)); assertEquals("3", dbref2.getVersion()); /* @@ -1028,8 +1227,8 @@ public class SequenceTest DBRefEntry dbref7 = new DBRefEntry(dbref3.getSource(), "3", dbref3.getAccessionId()); sq.addDBRef(dbref7); - assertEquals(4, sq.getDBRefs().length); - assertSame(dbref3, sq.getDBRefs()[2]); + assertEquals(4, sq.getDBRefs().size()); + assertSame(dbref3, sq.getDBRefs().get(2)); assertEquals("3", dbref2.getVersion()); } @@ -1043,7 +1242,7 @@ public class SequenceTest assertTrue(primaryDBRefs.isEmpty()); // empty dbrefs - sq.setDBRefs(new DBRefEntry[] {}); + sq.setDBRefs(null); primaryDBRefs = sq.getPrimaryDBRefs(); assertTrue(primaryDBRefs.isEmpty()); @@ -1252,146 +1451,207 @@ public class SequenceTest seq.setDatasetSequence(seq2); } - @Test - public void testFindPositions() + @Test(groups = { "Functional" }) + public void testFindFeatures() { - SequenceI sq = new Sequence("Seq", "ABC--DE-F", 8, 13); - - Range range = sq.findPositions(1, 4); // BC - assertEquals(new Range(9, 10), range); - - range = sq.findPositions(2, 4); // C - assertEquals(new Range(10, 10), range); - - assertNull(sq.findPositions(3, 4)); // all gaps + SequenceI sq = new Sequence("test/8-16", "-ABC--DEF--GHI--"); + sq.createDatasetSequence(); - range = sq.findPositions(2, 6); // CDE - assertEquals(new Range(10, 12), range); + assertTrue(sq.findFeatures(1, 99).isEmpty()); - range = sq.findPositions(3, 7); // DE - assertEquals(new Range(11, 12), range); + // add non-positional feature + SequenceFeature sf0 = new SequenceFeature("Cath", "desc", 0, 0, 2f, + null); + sq.addSequenceFeature(sf0); + // add feature on BCD + SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 9, 11, 2f, + null); + sq.addSequenceFeature(sfBCD); + // add feature on DE + SequenceFeature sfDE = new SequenceFeature("Cath", "desc", 11, 12, 2f, + null); + sq.addSequenceFeature(sfDE); + // add contact feature at [B, H] + SequenceFeature sfContactBH = new SequenceFeature("Disulphide bond", + "desc", 9, 15, 2f, null); + sq.addSequenceFeature(sfContactBH); + // add contact feature at [F, G] + SequenceFeature sfContactFG = new SequenceFeature("Disulfide Bond", + "desc", 13, 14, 2f, null); + sq.addSequenceFeature(sfContactFG); + // add single position feature at [I] + SequenceFeature sfI = new SequenceFeature("Disulfide Bond", + "desc", 16, 16, null); + sq.addSequenceFeature(sfI); + + // no features in columns 1-2 (-A) + List found = sq.findFeatures(1, 2); + assertTrue(found.isEmpty()); + + // columns 1-6 (-ABC--) includes BCD and B/H feature but not DE + found = sq.findFeatures(1, 6); + assertEquals(2, found.size()); + assertTrue(found.contains(sfBCD)); + assertTrue(found.contains(sfContactBH)); + + // columns 5-6 (--) includes (enclosing) BCD but not (contact) B/H feature + found = sq.findFeatures(5, 6); + assertEquals(1, found.size()); + assertTrue(found.contains(sfBCD)); + + // columns 7-10 (DEF-) includes BCD, DE, F/G but not B/H feature + found = sq.findFeatures(7, 10); + assertEquals(3, found.size()); + assertTrue(found.contains(sfBCD)); + assertTrue(found.contains(sfDE)); + assertTrue(found.contains(sfContactFG)); + + // columns 10-11 (--) should find nothing + found = sq.findFeatures(10, 11); + assertEquals(0, found.size()); + + // columns 14-14 (I) should find variant feature + found = sq.findFeatures(14, 14); + assertEquals(1, found.size()); + assertTrue(found.contains(sfI)); } @Test(groups = { "Functional" }) public void testFindIndex_withCursor() { Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--"); + final int tok = (int) PA.getValue(sq, "changeCount"); + assertEquals(1, tok); - // find F given A - assertEquals(10, sq.findIndex(13, new SequenceCursor(sq, 8, 2, 0))); + // find F given A, check cursor is now at the found position + assertEquals(10, sq.findIndex(13, new SequenceCursor(sq, 8, 2, tok))); + SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(13, cursor.residuePosition); + assertEquals(10, cursor.columnPosition); // find A given F - assertEquals(2, sq.findIndex(8, new SequenceCursor(sq, 13, 10, 0))); + assertEquals(2, sq.findIndex(8, new SequenceCursor(sq, 13, 10, tok))); + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(8, cursor.residuePosition); + assertEquals(2, cursor.columnPosition); + + // find C given C (no cursor update is done for this case) + assertEquals(6, sq.findIndex(10, new SequenceCursor(sq, 10, 6, tok))); + SequenceCursor cursor2 = (SequenceCursor) PA.getValue(sq, "cursor"); + assertSame(cursor2, cursor); + + /* + * sequence 'end' beyond end of sequence returns length of sequence + * (for compatibility with pre-cursor code) + * - also verify the cursor is left in a valid state + */ + sq = new Sequence("test/8-99", "-A--B-C-D-E-F--"); // trailing gap case + assertEquals(7, sq.findIndex(10)); // establishes a cursor + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(10, cursor.residuePosition); + assertEquals(7, cursor.columnPosition); + assertEquals(sq.getLength(), sq.findIndex(65)); + cursor2 = (SequenceCursor) PA.getValue(sq, "cursor"); + assertSame(cursor, cursor2); // not updated for this case! + + sq = new Sequence("test/8-99", "-A--B-C-D-E-F"); // trailing residue case + sq.findIndex(10); // establishes a cursor + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(sq.getLength(), sq.findIndex(65)); + cursor2 = (SequenceCursor) PA.getValue(sq, "cursor"); + assertSame(cursor, cursor2); // not updated for this case! + + /* + * residue after sequence 'start' but before first residue should return + * zero (for compatibility with pre-cursor code) + */ + sq = new Sequence("test/8-15", "-A-B-C-"); // leading gap case + sq.findIndex(10); // establishes a cursor + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(0, sq.findIndex(3)); + cursor2 = (SequenceCursor) PA.getValue(sq, "cursor"); + assertSame(cursor, cursor2); // not updated for this case! - // find C given C - assertEquals(6, sq.findIndex(10, new SequenceCursor(sq, 10, 6, 0))); + sq = new Sequence("test/8-15", "A-B-C-"); // leading residue case + sq.findIndex(10); // establishes a cursor + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(0, sq.findIndex(2)); + cursor2 = (SequenceCursor) PA.getValue(sq, "cursor"); + assertSame(cursor, cursor2); // not updated for this case! } @Test(groups = { "Functional" }) public void testFindPosition_withCursor() { Sequence sq = new Sequence("test/8-13", "-A--BCD-EF--"); + final int tok = (int) PA.getValue(sq, "changeCount"); + assertEquals(1, tok); - // find F pos given A - assertEquals(13, sq.findPosition(10, new SequenceCursor(sq, 8, 2, 0))); - int token = (int) PA.getValue(sq, "changeCount"); // 0 - SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 13, 10, token), cursor); - - // find A pos given F - assertEquals(8, sq.findPosition(2, new SequenceCursor(sq, 13, 10, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 8, 2, token), cursor); + // find F pos given A - lastCol gets set in cursor + assertEquals(13, + sq.findPosition(10, new SequenceCursor(sq, 8, 2, tok))); + assertEquals("test:Pos13:Col10:startCol0:endCol10:tok1", + PA.getValue(sq, "cursor").toString()); + + // find A pos given F - first residue column is saved in cursor + assertEquals(8, + sq.findPosition(2, new SequenceCursor(sq, 13, 10, tok))); + assertEquals("test:Pos8:Col2:startCol2:endCol10:tok1", + PA.getValue(sq, "cursor").toString()); - // find C pos given C - assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 10, 6, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 10, 6, token), cursor); + // find C pos given C (neither startCol nor endCol is set) + assertEquals(10, + sq.findPosition(6, new SequenceCursor(sq, 10, 6, tok))); + assertEquals("test:Pos10:Col6:startCol0:endCol0:tok1", + PA.getValue(sq, "cursor").toString()); // now the grey area - what residue position for a gapped column? JAL-2562 // find 'residue' for column 3 given cursor for D (so working left) // returns B9; cursor is updated to [B 5] - assertEquals(9, sq.findPosition(3, new SequenceCursor(sq, 11, 7, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 9, 5, token), cursor); + assertEquals(9, sq.findPosition(3, new SequenceCursor(sq, 11, 7, tok))); + assertEquals("test:Pos9:Col5:startCol0:endCol0:tok1", + PA.getValue(sq, "cursor").toString()); // find 'residue' for column 8 given cursor for D (so working right) // returns E12; cursor is updated to [D 7] - assertEquals(12, sq.findPosition(8, new SequenceCursor(sq, 11, 7, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 11, 7, token), cursor); + assertEquals(12, + sq.findPosition(8, new SequenceCursor(sq, 11, 7, tok))); + assertEquals("test:Pos11:Col7:startCol0:endCol0:tok1", + PA.getValue(sq, "cursor").toString()); // find 'residue' for column 12 given cursor for B // returns 1 more than last residue position; cursor is updated to [F 10] - assertEquals(14, sq.findPosition(12, new SequenceCursor(sq, 9, 5, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 13, 10, token), cursor); + // lastCol position is saved in cursor + assertEquals(14, + sq.findPosition(12, new SequenceCursor(sq, 9, 5, tok))); + assertEquals("test:Pos13:Col10:startCol0:endCol10:tok1", + PA.getValue(sq, "cursor").toString()); /* * findPosition for column beyond length of sequence * returns 1 more than the last residue position * cursor is set to last real residue position [F 10] */ - assertEquals(14, sq.findPosition(99, new SequenceCursor(sq, 8, 2, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 13, 10, token), cursor); + assertEquals(14, + sq.findPosition(99, new SequenceCursor(sq, 8, 2, tok))); + assertEquals("test:Pos13:Col10:startCol0:endCol10:tok1", + PA.getValue(sq, "cursor").toString()); /* * and the case without a trailing gap */ sq = new Sequence("test/8-13", "-A--BCD-EF"); // first find C from A - assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 8, 2, 0))); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 10, 6, token), cursor); + assertEquals(10, sq.findPosition(6, new SequenceCursor(sq, 8, 2, tok))); + SequenceCursor cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals("test:Pos10:Col6:startCol0:endCol0:tok1", + cursor.toString()); // now 'find' 99 from C - // cursor is set to [F 10] + // cursor is set to [F 10] and saved lastCol assertEquals(14, sq.findPosition(99, cursor)); - cursor = (SequenceCursor) PA.getValue(sq, "cursor"); - assertEquals(new SequenceCursor(sq, 13, 10, token), cursor); - } - - @Test - public void testFindPositions_withCursor() - { - Sequence sq = new Sequence("Seq", "ABC--DE-F", 8, 13); - - // find positions for columns 1-4 (BC--) given E cursor - Range range = sq.findPositions(1, 4, new SequenceCursor(sq, 12, 7, 0)); // BC - assertEquals(new Range(9, 10), range); - - // repeat using B cursor - range = sq.findPositions(1, 4, new SequenceCursor(sq, 9, 2, 0)); // BC - assertEquals(new Range(9, 10), range); - - // find positions for columns 2-4 (C--) given A cursor - range = sq.findPositions(2, 4, new SequenceCursor(sq, 8, 1, 0)); // C - assertEquals(new Range(10, 10), range); - - // gapped region - assertNull(sq.findPositions(3, 4, new SequenceCursor(sq, 10, 3, 0))); - assertNull(sq.findPositions(3, 4, new SequenceCursor(sq, 12, 7, 0))); - - // find positions for columns 2-6 (C--DE) given B cursor - range = sq.findPositions(2, 6, new SequenceCursor(sq, 9, 2, 0)); // CDE - assertEquals(new Range(10, 12), range); - - // repeat using C as cursor - range = sq.findPositions(2, 6, new SequenceCursor(sq, 10, 3, 0)); - assertEquals(new Range(10, 12), range); - - // repeat using D as cursor - range = sq.findPositions(2, 6, new SequenceCursor(sq, 11, 6, 0)); - assertEquals(new Range(10, 12), range); - - // repeat using E as cursor - range = sq.findPositions(2, 6, new SequenceCursor(sq, 12, 7, 0)); - assertEquals(new Range(10, 12), range); - - // repeat using F as cursor - range = sq.findPositions(2, 6, new SequenceCursor(sq, 13, 9, 0)); - assertEquals(new Range(10, 12), range); + assertEquals("test:Pos13:Col10:startCol0:endCol10:tok1", + PA.getValue(sq, "cursor").toString()); } @Test @@ -1409,11 +1669,11 @@ public class SequenceTest assertTrue(sq.isValidCursor(cursor)); /* - * column position outside [0 - length-1] is rejected + * column position outside [0 - length] is rejected */ cursor = new SequenceCursor(sq, 13, -1, changeCount); assertFalse(sq.isValidCursor(cursor)); - cursor = new SequenceCursor(sq, 13, 9, changeCount); + cursor = new SequenceCursor(sq, 13, 10, changeCount); assertFalse(sq.isValidCursor(cursor)); cursor = new SequenceCursor(sq, 7, 8, changeCount); assertFalse(sq.isValidCursor(cursor)); @@ -1458,6 +1718,10 @@ public class SequenceTest // cursor should now be at [D 6] cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 11, 6, ++token), cursor); + assertEquals(0, cursor.lastColumnPosition); // not yet found + assertEquals(13, sq.findPosition(8)); // E13 + cursor = (SequenceCursor) PA.getValue(sq, "cursor"); + assertEquals(9, cursor.lastColumnPosition); // found /* * deleteChars should invalidate the cached cursor @@ -1493,5 +1757,460 @@ public class SequenceTest // cursor should now be at [F 10] cursor = (SequenceCursor) PA.getValue(sq, "cursor"); assertEquals(new SequenceCursor(sq, 13, 10, ++token), cursor); + + /* + * changing sequence start should invalidate cursor + */ + sq = new Sequence("test/8-13", "-A--BCD-EF--"); + assertEquals(8, sq.getStart()); + assertEquals(9, sq.findPosition(4)); // B(9) + sq.setStart(7); + assertEquals(8, sq.findPosition(4)); // is now B(8) + sq.setStart(10); + assertEquals(11, sq.findPosition(4)); // is now B(11) + } + + @Test(groups = { "Functional" }) + public void testGetSequence() + { + String seqstring = "-A--BCD-EF--"; + Sequence sq = new Sequence("test/8-13", seqstring); + sq.createDatasetSequence(); + assertTrue(Arrays.equals(sq.getSequence(), seqstring.toCharArray())); + assertTrue(Arrays.equals(sq.getDatasetSequence().getSequence(), + "ABCDEF".toCharArray())); + + // verify a copy of the sequence array is returned + char[] theSeq = (char[]) PA.getValue(sq, "sequence"); + assertNotSame(theSeq, sq.getSequence()); + theSeq = (char[]) PA.getValue(sq.getDatasetSequence(), "sequence"); + assertNotSame(theSeq, sq.getDatasetSequence().getSequence()); + } + + @Test(groups = { "Functional" }) + public void testReplace() + { + String seqstring = "-A--BCD-EF--"; + SequenceI sq = new Sequence("test/8-13", seqstring); + // changeCount is incremented for setStart + assertEquals(1, PA.getValue(sq, "changeCount")); + + assertEquals(0, sq.replace('A', 'A')); // same char + assertEquals(seqstring, sq.getSequenceAsString()); + assertEquals(1, PA.getValue(sq, "changeCount")); + + assertEquals(0, sq.replace('X', 'Y')); // not there + assertEquals(seqstring, sq.getSequenceAsString()); + assertEquals(1, PA.getValue(sq, "changeCount")); + + assertEquals(1, sq.replace('A', 'K')); + assertEquals("-K--BCD-EF--", sq.getSequenceAsString()); + assertEquals(2, PA.getValue(sq, "changeCount")); + + assertEquals(6, sq.replace('-', '.')); + assertEquals(".K..BCD.EF..", sq.getSequenceAsString()); + assertEquals(3, PA.getValue(sq, "changeCount")); + } + + @Test(groups = { "Functional" }) + public void testGapBitset() + { + SequenceI sq = new Sequence("test/8-13", "-ABC---DE-F--"); + BitSet bs = sq.gapBitset(); + BitSet expected = new BitSet(); + expected.set(0); + expected.set(4, 7); + expected.set(9); + expected.set(11, 13); + + assertTrue(bs.equals(expected)); + + } + + public void testFindFeatures_largeEndPos() + { + /* + * imitate a PDB sequence where end is larger than end position + */ + SequenceI sq = new Sequence("test", "-ABC--DEF--", 1, 20); + sq.createDatasetSequence(); + + assertTrue(sq.findFeatures(1, 9).isEmpty()); + // should be no array bounds exception - JAL-2772 + assertTrue(sq.findFeatures(1, 15).isEmpty()); + + // add feature on BCD + SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 2, 4, 2f, + null); + sq.addSequenceFeature(sfBCD); + + // no features in columns 1-2 (-A) + List found = sq.findFeatures(1, 2); + assertTrue(found.isEmpty()); + + // columns 1-6 (-ABC--) includes BCD + found = sq.findFeatures(1, 6); + assertEquals(1, found.size()); + assertTrue(found.contains(sfBCD)); + + // columns 10-11 (--) should find nothing + found = sq.findFeatures(10, 11); + assertEquals(0, found.size()); + } + + @Test(groups = { "Functional" }) + public void testSetName() + { + SequenceI sq = new Sequence("test", "-ABC---DE-F--"); + assertEquals("test", sq.getName()); + assertEquals(1, sq.getStart()); + assertEquals(6, sq.getEnd()); + + sq.setName("testing"); + assertEquals("testing", sq.getName()); + + sq.setName("test/8-10"); + assertEquals("test", sq.getName()); + assertEquals(8, sq.getStart()); + assertEquals(13, sq.getEnd()); // note end is recomputed + + sq.setName("testing/7-99"); + assertEquals("testing", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); // end may be beyond physical end + + sq.setName("/2-3"); + assertEquals("", sq.getName()); + assertEquals(2, sq.getStart()); + assertEquals(7, sq.getEnd()); + + sq.setName("test/"); // invalid + assertEquals("test/", sq.getName()); + assertEquals(2, sq.getStart()); + assertEquals(7, sq.getEnd()); + + sq.setName("test/6-13/7-99"); + assertEquals("test/6-13", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/0-5"); // 0 is invalid - ignored + assertEquals("test/0-5", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/a-5"); // a is invalid - ignored + assertEquals("test/a-5", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/6-5"); // start > end is invalid - ignored + assertEquals("test/6-5", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/5"); // invalid - ignored + assertEquals("test/5", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/-5"); // invalid - ignored + assertEquals("test/-5", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/5-"); // invalid - ignored + assertEquals("test/5-", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName("test/5-6-7"); // invalid - ignored + assertEquals("test/5-6-7", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + + sq.setName(null); // invalid, gets converted to space + assertEquals("", sq.getName()); + assertEquals(7, sq.getStart()); + assertEquals(99, sq.getEnd()); + } + + @Test(groups = { "Functional" }) + public void testCheckValidRange() + { + Sequence sq = new Sequence("test/7-12", "-ABC---DE-F--"); + assertEquals(7, sq.getStart()); + assertEquals(12, sq.getEnd()); + + /* + * checkValidRange ensures end is at least the last residue position + */ + PA.setValue(sq, "end", 2); + sq.checkValidRange(); + assertEquals(12, sq.getEnd()); + + /* + * end may be beyond the last residue position + */ + PA.setValue(sq, "end", 22); + sq.checkValidRange(); + assertEquals(22, sq.getEnd()); + } + + @Test(groups = { "Functional" }) + public void testDeleteChars_withGaps() + { + /* + * delete gaps only + */ + SequenceI sq = new Sequence("test/8-10", "A-B-C"); + sq.createDatasetSequence(); + assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString()); + sq.deleteChars(1, 2); // delete first gap + assertEquals("AB-C", sq.getSequenceAsString()); + assertEquals(8, sq.getStart()); + assertEquals(10, sq.getEnd()); + assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString()); + + /* + * delete gaps and residues at start (no new dataset sequence) + */ + sq = new Sequence("test/8-10", "A-B-C"); + sq.createDatasetSequence(); + sq.deleteChars(0, 3); // delete A-B + assertEquals("-C", sq.getSequenceAsString()); + assertEquals(10, sq.getStart()); + assertEquals(10, sq.getEnd()); + assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString()); + + /* + * delete gaps and residues at end (no new dataset sequence) + */ + sq = new Sequence("test/8-10", "A-B-C"); + sq.createDatasetSequence(); + sq.deleteChars(2, 5); // delete B-C + assertEquals("A-", sq.getSequenceAsString()); + assertEquals(8, sq.getStart()); + assertEquals(8, sq.getEnd()); + assertEquals("ABC", sq.getDatasetSequence().getSequenceAsString()); + + /* + * delete gaps and residues internally (new dataset sequence) + * first delete from gap to residue + */ + sq = new Sequence("test/8-10", "A-B-C"); + sq.createDatasetSequence(); + sq.deleteChars(1, 3); // delete -B + assertEquals("A-C", sq.getSequenceAsString()); + assertEquals(8, sq.getStart()); + assertEquals(9, sq.getEnd()); + assertEquals("AC", sq.getDatasetSequence().getSequenceAsString()); + assertEquals(8, sq.getDatasetSequence().getStart()); + assertEquals(9, sq.getDatasetSequence().getEnd()); + + /* + * internal delete from gap to gap + */ + sq = new Sequence("test/8-10", "A-B-C"); + sq.createDatasetSequence(); + sq.deleteChars(1, 4); // delete -B- + assertEquals("AC", sq.getSequenceAsString()); + assertEquals(8, sq.getStart()); + assertEquals(9, sq.getEnd()); + assertEquals("AC", sq.getDatasetSequence().getSequenceAsString()); + assertEquals(8, sq.getDatasetSequence().getStart()); + assertEquals(9, sq.getDatasetSequence().getEnd()); + + /* + * internal delete from residue to residue + */ + sq = new Sequence("test/8-10", "A-B-C"); + sq.createDatasetSequence(); + sq.deleteChars(2, 3); // delete B + assertEquals("A--C", sq.getSequenceAsString()); + assertEquals(8, sq.getStart()); + assertEquals(9, sq.getEnd()); + assertEquals("AC", sq.getDatasetSequence().getSequenceAsString()); + assertEquals(8, sq.getDatasetSequence().getStart()); + assertEquals(9, sq.getDatasetSequence().getEnd()); + } + + /** + * Test the code used to locate the reference sequence ruler origin + */ + @Test(groups = { "Functional" }) + public void testLocateVisibleStartofSequence() + { + // create random alignment + AlignmentGenerator gen = new AlignmentGenerator(false); + AlignmentI al = gen.generate(50, 20, 123, 5, 5); + + HiddenColumns cs = al.getHiddenColumns(); + ColumnSelection colsel = new ColumnSelection(); + + SequenceI seq = new Sequence("RefSeq", "-A-SD-ASD--E---"); + assertEquals(2, seq.findIndex(seq.getStart())); + + // no hidden columns + assertEquals(seq.findIndex(seq.getStart()) - 1, + seq.firstResidueOutsideIterator(cs.iterator())); + + // hidden column on gap after end of sequence - should not affect bounds + colsel.hideSelectedColumns(13, al.getHiddenColumns()); + assertEquals(seq.findIndex(seq.getStart()) - 1, + seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + // hidden column on gap before beginning of sequence - should vis bounds by + // one + colsel.hideSelectedColumns(0, al.getHiddenColumns()); + assertEquals(seq.findIndex(seq.getStart()) - 2, + cs.absoluteToVisibleColumn( + seq.firstResidueOutsideIterator(cs.iterator()))); + + cs.revealAllHiddenColumns(colsel); + // hide columns around most of sequence - leave one residue remaining + cs.hideColumns(1, 3); + cs.hideColumns(6, 11); + + Iterator it = cs.getVisContigsIterator(0, 6, false); + + assertEquals("-D", seq.getSequenceStringFromIterator(it)); + // cs.getVisibleSequenceStrings(0, 5, new SequenceI[] + // { seq })[0]); + + assertEquals(4, seq.firstResidueOutsideIterator(cs.iterator())); + cs.revealAllHiddenColumns(colsel); + + // hide whole sequence - should just get location of hidden region + // containing sequence + cs.hideColumns(1, 11); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 15); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + SequenceI seq2 = new Sequence("RefSeq2", "-------A-SD-ASD--E---"); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(7, 17); + assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(3, 17); + assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(3, 19); + assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 0); + assertEquals(1, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 1); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 2); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(1, 1); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(1, 2); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(1, 3); + assertEquals(4, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 2); + cs.hideColumns(5, 6); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 2); + cs.hideColumns(5, 6); + cs.hideColumns(9, 10); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 2); + cs.hideColumns(7, 11); + assertEquals(3, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(2, 4); + cs.hideColumns(7, 11); + assertEquals(1, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(2, 4); + cs.hideColumns(7, 12); + assertEquals(1, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(1, 11); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 12); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 4); + cs.hideColumns(6, 12); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 1); + cs.hideColumns(3, 12); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(3, 14); + cs.hideColumns(17, 19); + assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(3, 7); + cs.hideColumns(9, 14); + cs.hideColumns(17, 19); + assertEquals(0, seq2.firstResidueOutsideIterator(cs.iterator())); + + cs.revealAllHiddenColumns(colsel); + cs.hideColumns(0, 1); + cs.hideColumns(3, 4); + cs.hideColumns(6, 8); + cs.hideColumns(10, 12); + assertEquals(0, seq.firstResidueOutsideIterator(cs.iterator())); + + } + @Test(groups= {"Functional"}) + public void testTransferAnnotation() { + Sequence origSeq = new Sequence("MYSEQ","THISISASEQ"); + Sequence toSeq = new Sequence("MYSEQ","THISISASEQ"); + origSeq.addDBRef(new DBRefEntry("UNIPROT", "0", "Q12345", null, true)); + toSeq.transferAnnotation(origSeq, null); + assertTrue(toSeq.getDBRefs().size()==1); + + assertTrue(toSeq.getDBRefs().get(0).isCanonical()); + + // check for promotion of non-canonical + // to canonical (e.g. fetch-db-refs on a jalview project pre 2.11.2) + toSeq.setDBRefs(null); + toSeq.addDBRef(new DBRefEntry("UNIPROT", "0", "Q12345", null, false)); + toSeq.transferAnnotation(origSeq, null); + assertTrue(toSeq.getDBRefs().size()==1); + + assertTrue("Promotion of non-canonical DBRefEntry failed",toSeq.getDBRefs().get(0).isCanonical()); + + } }