JAL-1645 source formatting and organise imports
[jalview.git] / test / jalview / datamodel / SequenceTest.java
1 package jalview.datamodel;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertNull;
5 import static org.testng.AssertJUnit.assertSame;
6 import static org.testng.AssertJUnit.assertTrue;
7
8 import java.util.Arrays;
9 import java.util.List;
10
11 import org.testng.annotations.BeforeMethod;
12 import org.testng.annotations.Test;
13
14 public class SequenceTest
15 {
16   SequenceI seq;
17
18   @BeforeMethod(alwaysRun = true)
19   public void setUp()
20   {
21     seq = new Sequence("FER1", "AKPNGVL");
22   }
23
24   @Test(groups = { "Functional" })
25   public void testInsertGapsAndGapmaps()
26   {
27     SequenceI aseq = seq.deriveSequence();
28     aseq.insertCharAt(2, 3, '-');
29     aseq.insertCharAt(6, 3, '-');
30     assertEquals("Gap insertions not correct", "AK---P---NGVL",
31             aseq.getSequenceAsString());
32     List<int[]> gapInt = aseq.getInsertions();
33     assertEquals("Gap interval 1 start wrong", 2, gapInt.get(0)[0]);
34     assertEquals("Gap interval 1 end wrong", 4, gapInt.get(0)[1]);
35     assertEquals("Gap interval 2 start wrong", 6, gapInt.get(1)[0]);
36     assertEquals("Gap interval 2 end wrong", 8, gapInt.get(1)[1]);
37   }
38
39   @Test(groups = { "Functional" })
40   public void testGetAnnotation()
41   {
42     // initial state returns null not an empty array
43     assertNull(seq.getAnnotation());
44     AlignmentAnnotation ann = addAnnotation("label1", "desc1", "calcId1",
45             1f);
46     AlignmentAnnotation[] anns = seq.getAnnotation();
47     assertEquals(1, anns.length);
48     assertSame(ann, anns[0]);
49
50     // removing all annotations reverts array to null
51     seq.removeAlignmentAnnotation(ann);
52     assertNull(seq.getAnnotation());
53   }
54
55   @Test(groups = { "Functional" })
56   public void testGetAnnotation_forLabel()
57   {
58     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
59             1f);
60     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
61             1f);
62     AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3",
63             1f);
64     AlignmentAnnotation[] anns = seq.getAnnotation("label1");
65     assertEquals(2, anns.length);
66     assertSame(ann1, anns[0]);
67     assertSame(ann3, anns[1]);
68   }
69
70   private AlignmentAnnotation addAnnotation(String label,
71           String description, String calcId, float value)
72   {
73     final AlignmentAnnotation annotation = new AlignmentAnnotation(label,
74             description, value);
75     annotation.setCalcId(calcId);
76     seq.addAlignmentAnnotation(annotation);
77     return annotation;
78   }
79
80   @Test(groups = { "Functional" })
81   public void testGetAlignmentAnnotations_forCalcIdAndLabel()
82   {
83     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
84             1f);
85     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
86             1f);
87     AlignmentAnnotation ann3 = addAnnotation("label2", "desc3", "calcId3",
88             1f);
89     AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
90             1f);
91     AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null, 1f);
92     AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3", 1f);
93     List<AlignmentAnnotation> anns = seq.getAlignmentAnnotations("calcId2",
94             "label2");
95     assertEquals(2, anns.size());
96     assertSame(ann2, anns.get(0));
97     assertSame(ann4, anns.get(1));
98
99     assertTrue(seq.getAlignmentAnnotations("calcId2", "label3").isEmpty());
100     assertTrue(seq.getAlignmentAnnotations("calcId3", "label5").isEmpty());
101     assertTrue(seq.getAlignmentAnnotations("calcId2", null).isEmpty());
102     assertTrue(seq.getAlignmentAnnotations(null, "label3").isEmpty());
103     assertTrue(seq.getAlignmentAnnotations(null, null).isEmpty());
104   }
105
106   /**
107    * Tests for addAlignmentAnnotation. Note this method has the side-effect of
108    * setting the sequenceRef on the annotation. Adding the same annotation twice
109    * should be ignored.
110    */
111   @Test(groups = { "Functional" })
112   public void testAddAlignmentAnnotation()
113   {
114     assertNull(seq.getAnnotation());
115     final AlignmentAnnotation annotation = new AlignmentAnnotation("a",
116             "b", 2d);
117     assertNull(annotation.sequenceRef);
118     seq.addAlignmentAnnotation(annotation);
119     assertSame(seq, annotation.sequenceRef);
120     AlignmentAnnotation[] anns = seq.getAnnotation();
121     assertEquals(1, anns.length);
122     assertSame(annotation, anns[0]);
123
124     // re-adding does nothing
125     seq.addAlignmentAnnotation(annotation);
126     anns = seq.getAnnotation();
127     assertEquals(1, anns.length);
128     assertSame(annotation, anns[0]);
129
130     // an identical but different annotation can be added
131     final AlignmentAnnotation annotation2 = new AlignmentAnnotation("a",
132             "b", 2d);
133     seq.addAlignmentAnnotation(annotation2);
134     anns = seq.getAnnotation();
135     assertEquals(2, anns.length);
136     assertSame(annotation, anns[0]);
137     assertSame(annotation2, anns[1]);
138
139   }
140
141   @Test(groups = { "Functional" })
142   public void testGetStartGetEnd()
143   {
144     SequenceI seq = new Sequence("test", "ABCDEF");
145     assertEquals(1, seq.getStart());
146     assertEquals(6, seq.getEnd());
147
148     seq = new Sequence("test", "--AB-C-DEF--");
149     assertEquals(1, seq.getStart());
150     assertEquals(6, seq.getEnd());
151
152     seq = new Sequence("test", "----");
153     assertEquals(1, seq.getStart());
154     assertEquals(0, seq.getEnd()); // ??
155   }
156
157   /**
158    * Tests for the method that returns an alignment column position (base 1) for
159    * a given sequence position (base 1).
160    */
161   @Test(groups = { "Functional" })
162   public void testFindIndex()
163   {
164     SequenceI seq = new Sequence("test", "ABCDEF");
165     assertEquals(0, seq.findIndex(0));
166     assertEquals(1, seq.findIndex(1));
167     assertEquals(5, seq.findIndex(5));
168     assertEquals(6, seq.findIndex(6));
169     assertEquals(6, seq.findIndex(9));
170
171     seq = new Sequence("test", "-A--B-C-D-E-F--");
172     assertEquals(2, seq.findIndex(1));
173     assertEquals(5, seq.findIndex(2));
174     assertEquals(7, seq.findIndex(3));
175
176     // before start returns 0
177     assertEquals(0, seq.findIndex(0));
178     assertEquals(0, seq.findIndex(-1));
179
180     // beyond end returns last residue column
181     assertEquals(13, seq.findIndex(99));
182
183   }
184
185   /**
186    * Tests for the method that returns a dataset sequence position (base 1) for
187    * an aligned column position (base 0).
188    */
189   @Test(groups = { "Functional" })
190   public void testFindPosition()
191   {
192     SequenceI seq = new Sequence("test", "ABCDEF");
193     assertEquals(1, seq.findPosition(0));
194     assertEquals(6, seq.findPosition(5));
195     // assertEquals(-1, seq.findPosition(6)); // fails
196
197     seq = new Sequence("test", "AB-C-D--");
198     assertEquals(1, seq.findPosition(0));
199     assertEquals(2, seq.findPosition(1));
200     // gap position 'finds' residue to the right (not the left as per javadoc)
201     assertEquals(3, seq.findPosition(2));
202     assertEquals(3, seq.findPosition(3));
203     assertEquals(4, seq.findPosition(4));
204     assertEquals(4, seq.findPosition(5));
205     // returns 1 more than sequence length if off the end ?!?
206     assertEquals(5, seq.findPosition(6));
207     assertEquals(5, seq.findPosition(7));
208
209     seq = new Sequence("test", "--AB-C-DEF--");
210     assertEquals(1, seq.findPosition(0));
211     assertEquals(1, seq.findPosition(1));
212     assertEquals(1, seq.findPosition(2));
213     assertEquals(2, seq.findPosition(3));
214     assertEquals(3, seq.findPosition(4));
215     assertEquals(3, seq.findPosition(5));
216     assertEquals(4, seq.findPosition(6));
217     assertEquals(4, seq.findPosition(7));
218     assertEquals(5, seq.findPosition(8));
219     assertEquals(6, seq.findPosition(9));
220     assertEquals(7, seq.findPosition(10));
221     assertEquals(7, seq.findPosition(11));
222   }
223
224   @Test(groups = { "Functional" })
225   public void testDeleteChars()
226   {
227     SequenceI seq = new Sequence("test", "ABCDEF");
228     assertEquals(1, seq.getStart());
229     assertEquals(6, seq.getEnd());
230     seq.deleteChars(2, 3);
231     assertEquals("ABDEF", seq.getSequenceAsString());
232     assertEquals(1, seq.getStart());
233     assertEquals(5, seq.getEnd());
234
235     seq = new Sequence("test", "ABCDEF");
236     seq.deleteChars(0, 2);
237     assertEquals("CDEF", seq.getSequenceAsString());
238     assertEquals(3, seq.getStart());
239     assertEquals(6, seq.getEnd());
240   }
241
242   @Test(groups = { "Functional" })
243   public void testInsertCharAt()
244   {
245     // non-static methods:
246     SequenceI seq = new Sequence("test", "ABCDEF");
247     seq.insertCharAt(0, 'z');
248     assertEquals("zABCDEF", seq.getSequenceAsString());
249     seq.insertCharAt(2, 2, 'x');
250     assertEquals("zAxxBCDEF", seq.getSequenceAsString());
251
252     // for static method see StringUtilsTest
253   }
254
255   /**
256    * Test the method that returns an array of aligned sequence positions where
257    * the array index is the data sequence position (both base 0).
258    */
259   @Test(groups = { "Functional" })
260   public void testGapMap()
261   {
262     SequenceI seq = new Sequence("test", "-A--B-CD-E--F-");
263     seq.createDatasetSequence();
264     assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(seq.gapMap()));
265   }
266
267   /**
268    * Test the method that gets sequence features, either from the sequence or
269    * its dataset.
270    */
271   @Test(groups = { "Functional" })
272   public void testGetSequenceFeatures()
273   {
274     SequenceI seq = new Sequence("test", "GATCAT");
275     seq.createDatasetSequence();
276
277     assertNull(seq.getSequenceFeatures());
278
279     /*
280      * SequenceFeature on sequence
281      */
282     SequenceFeature sf = new SequenceFeature();
283     seq.addSequenceFeature(sf);
284     SequenceFeature[] sfs = seq.getSequenceFeatures();
285     assertEquals(1, sfs.length);
286     assertSame(sf, sfs[0]);
287
288     /*
289      * SequenceFeature on sequence and dataset sequence; returns that on
290      * sequence
291      */
292     SequenceFeature sf2 = new SequenceFeature();
293     seq.getDatasetSequence().addSequenceFeature(sf2);
294     sfs = seq.getSequenceFeatures();
295     assertEquals(1, sfs.length);
296     assertSame(sf, sfs[0]);
297
298     /*
299      * SequenceFeature on dataset sequence only
300      */
301     seq.setSequenceFeatures(null);
302     sfs = seq.getSequenceFeatures();
303     assertEquals(1, sfs.length);
304     assertSame(sf2, sfs[0]);
305
306     /*
307      * Corrupt case - no SequenceFeature, dataset's dataset is the original
308      * sequence. Test shows no infinite loop results.
309      */
310     seq.getDatasetSequence().setSequenceFeatures(null);
311     seq.getDatasetSequence().setDatasetSequence(seq); // loop!
312     assertNull(seq.getSequenceFeatures());
313   }
314
315   /**
316    * Test the method that returns an array, indexed by sequence position, whose
317    * entries are the residue positions at the sequence position (or to the right
318    * if a gap)
319    */
320   @Test(groups = { "Functional" })
321   public void testFindPositionMap()
322   {
323     /*
324      * Note: Javadoc for findPosition says it returns the residue position to
325      * the left of a gapped position; in fact it returns the position to the
326      * right. Also it returns a non-existent residue position for a gap beyond
327      * the sequence.
328      */
329     Sequence seq = new Sequence("TestSeq", "AB.C-D E.");
330     int[] map = seq.findPositionMap();
331     assertEquals(Arrays.toString(new int[] { 1, 2, 3, 3, 4, 4, 5, 5, 6 }),
332             Arrays.toString(map));
333   }
334
335   /**
336    * Test for getSubsequence
337    */
338   @Test(groups = { "Functional" })
339   public void testGetSubsequence()
340   {
341     SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
342     seq.createDatasetSequence();
343
344     // positions are base 0, end position is exclusive
345     SequenceI subseq = seq.getSubSequence(2, 4);
346
347     assertEquals("CD", subseq.getSequenceAsString());
348     // start/end are base 1 positions
349     assertEquals(3, subseq.getStart());
350     assertEquals(4, subseq.getEnd());
351     // subsequence shares the full dataset sequence
352     assertSame(seq.getDatasetSequence(), subseq.getDatasetSequence());
353   }
354
355   /**
356    * Test for deriveSequence applied to a sequence with a dataset
357    */
358   @Test(groups = { "Functional" })
359   public void testDeriveSequence_existingDataset()
360   {
361     SequenceI seq = new Sequence("Seq1", "CD");
362     seq.setDatasetSequence(new Sequence("Seq1", "ABCDEF"));
363     seq.setStart(3);
364     seq.setEnd(4);
365     SequenceI derived = seq.deriveSequence();
366     assertEquals("CD", derived.getSequenceAsString());
367     assertSame(seq.getDatasetSequence(), derived.getDatasetSequence());
368   }
369
370   /**
371    * Test for deriveSequence applied to an ungapped sequence with no dataset
372    */
373   @Test(groups = { "Functional" })
374   public void testDeriveSequence_noDatasetUngapped()
375   {
376     SequenceI seq = new Sequence("Seq1", "ABCDEF");
377     assertEquals(1, seq.getStart());
378     assertEquals(6, seq.getEnd());
379     SequenceI derived = seq.deriveSequence();
380     assertEquals("ABCDEF", derived.getSequenceAsString());
381     assertEquals("ABCDEF", derived.getDatasetSequence()
382             .getSequenceAsString());
383   }
384
385   /**
386    * Test for deriveSequence applied to a gapped sequence with no dataset
387    */
388   @Test(groups = { "Functional" })
389   public void testDeriveSequence_noDatasetGapped()
390   {
391     SequenceI seq = new Sequence("Seq1", "AB-C.D EF");
392     assertEquals(1, seq.getStart());
393     assertEquals(6, seq.getEnd());
394     assertNull(seq.getDatasetSequence());
395     SequenceI derived = seq.deriveSequence();
396     assertEquals("AB-C.D EF", derived.getSequenceAsString());
397     assertEquals("ABCDEF", derived.getDatasetSequence()
398             .getSequenceAsString());
399   }
400 }