JAL-1665 refactored Sequence.getSequenceFeatures
[jalview.git] / test / jalview / datamodel / SequenceTest.java
1 package jalview.datamodel;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertNull;
5 import static org.junit.Assert.assertSame;
6 import static org.junit.Assert.assertTrue;
7
8 import java.util.Arrays;
9 import java.util.List;
10
11 import org.junit.Before;
12 import org.junit.Test;
13
14 public class SequenceTest
15 {
16   SequenceI seq;
17
18   @Before
19   public void setUp()
20   {
21     seq = new Sequence("FER1", "AKPNGVL");
22   }
23   @Test
24   public void testInsertGapsAndGapmaps()
25   {
26     SequenceI aseq = seq.deriveSequence();
27     aseq.insertCharAt(2, 3, '-');
28     aseq.insertCharAt(6, 3, '-');
29     assertEquals("Gap insertions not correct", "AK---P---NGVL",
30             aseq.getSequenceAsString());
31     List<int[]> gapInt = aseq.getInsertions();
32     assertEquals("Gap interval 1 start wrong", 2, gapInt.get(0)[0]);
33     assertEquals("Gap interval 1 end wrong", 4, gapInt.get(0)[1]);
34     assertEquals("Gap interval 2 start wrong", 6, gapInt.get(1)[0]);
35     assertEquals("Gap interval 2 end wrong", 8, gapInt.get(1)[1]);
36   }
37
38   @Test
39   public void testGetAnnotation()
40   {
41     // initial state returns null not an empty array
42     assertNull(seq.getAnnotation());
43     AlignmentAnnotation ann = addAnnotation("label1", "desc1", "calcId1",
44             1f);
45     AlignmentAnnotation[] anns = seq.getAnnotation();
46     assertEquals(1, anns.length);
47     assertSame(ann, anns[0]);
48
49     // removing all annotations reverts array to null
50     seq.removeAlignmentAnnotation(ann);
51     assertNull(seq.getAnnotation());
52   }
53
54   @Test
55   public void testGetAnnotation_forLabel()
56   {
57     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1", 1f);
58     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2", 1f);
59     AlignmentAnnotation ann3 = addAnnotation("label1", "desc3", "calcId3", 1f);
60     AlignmentAnnotation[] anns = seq.getAnnotation("label1");
61     assertEquals(2, anns.length);
62     assertSame(ann1, anns[0]);
63     assertSame(ann3, anns[1]);
64   }
65
66   private AlignmentAnnotation addAnnotation(String label,
67           String description, String calcId,
68           float value)
69   {
70     final AlignmentAnnotation annotation = new AlignmentAnnotation(label, description,
71             value);
72     annotation.setCalcId(calcId);
73     seq.addAlignmentAnnotation(annotation);
74     return annotation;
75   }
76
77   @Test
78   public void testGetAlignmentAnnotations_forCalcIdAndLabel()
79   {
80     AlignmentAnnotation ann1 = addAnnotation("label1", "desc1", "calcId1",
81             1f);
82     AlignmentAnnotation ann2 = addAnnotation("label2", "desc2", "calcId2",
83             1f);
84     AlignmentAnnotation ann3 = addAnnotation("label2", "desc3", "calcId3",
85             1f);
86     AlignmentAnnotation ann4 = addAnnotation("label2", "desc3", "calcId2",
87             1f);
88     AlignmentAnnotation ann5 = addAnnotation("label5", "desc3", null,
89             1f);
90     AlignmentAnnotation ann6 = addAnnotation(null, "desc3", "calcId3",
91             1f);
92     List<AlignmentAnnotation> anns = seq.getAlignmentAnnotations("calcId2",
93             "label2");
94     assertEquals(2, anns.size());
95     assertSame(ann2, anns.get(0));
96     assertSame(ann4, anns.get(1));
97     
98     assertTrue(seq.getAlignmentAnnotations("calcId2", "label3").isEmpty());
99     assertTrue(seq.getAlignmentAnnotations("calcId3", "label5").isEmpty());
100     assertTrue(seq.getAlignmentAnnotations("calcId2", null).isEmpty());
101     assertTrue(seq.getAlignmentAnnotations(null, "label3").isEmpty());
102     assertTrue(seq.getAlignmentAnnotations(null, null).isEmpty());
103   }
104
105   /**
106    * Tests for addAlignmentAnnotation. Note this method has the side-effect of
107    * setting the sequenceRef on the annotation. Adding the same annotation twice
108    * should be ignored.
109    */
110   @Test
111   public void testAddAlignmentAnnotation()
112   {
113     assertNull(seq.getAnnotation());
114     final AlignmentAnnotation annotation = new AlignmentAnnotation("a",
115             "b", 2d);
116     assertNull(annotation.sequenceRef);
117     seq.addAlignmentAnnotation(annotation);
118     assertSame(seq, annotation.sequenceRef);
119     AlignmentAnnotation[] anns = seq.getAnnotation();
120     assertEquals(1, anns.length);
121     assertSame(annotation, anns[0]);
122
123     // re-adding does nothing
124     seq.addAlignmentAnnotation(annotation);
125     anns = seq.getAnnotation();
126     assertEquals(1, anns.length);
127     assertSame(annotation, anns[0]);
128
129     // an identical but different annotation can be added
130     final AlignmentAnnotation annotation2 = new AlignmentAnnotation("a",
131             "b", 2d);
132     seq.addAlignmentAnnotation(annotation2);
133     anns = seq.getAnnotation();
134     assertEquals(2, anns.length);
135     assertSame(annotation, anns[0]);
136     assertSame(annotation2, anns[1]);
137
138   }
139
140   @Test
141   public void testGetStartGetEnd()
142   {
143     SequenceI seq = new Sequence("test", "ABCDEF");
144     assertEquals(1, seq.getStart());
145     assertEquals(6, seq.getEnd());
146
147     seq = new Sequence("test", "--AB-C-DEF--");
148     assertEquals(1, seq.getStart());
149     assertEquals(6, seq.getEnd());
150
151     seq = new Sequence("test", "----");
152     assertEquals(1, seq.getStart());
153     assertEquals(0, seq.getEnd()); // ??
154   }
155
156   /**
157    * Tests for the method that returns an alignment column position (base 1) for
158    * a given sequence position (base 1).
159    */
160   @Test
161   public void testFindIndex()
162   {
163     SequenceI seq = new Sequence("test", "ABCDEF");
164     assertEquals(0, seq.findIndex(0));
165     assertEquals(1, seq.findIndex(1));
166     assertEquals(5, seq.findIndex(5));
167     assertEquals(6, seq.findIndex(6));
168     assertEquals(6, seq.findIndex(9));
169
170     seq = new Sequence("test", "-A--B-C-D-E-F--");
171     assertEquals(2, seq.findIndex(1));
172     assertEquals(5, seq.findIndex(2));
173     assertEquals(7, seq.findIndex(3));
174
175     // before start returns 0
176     assertEquals(0, seq.findIndex(0));
177     assertEquals(0, seq.findIndex(-1));
178
179     // beyond end returns last residue column
180     assertEquals(13, seq.findIndex(99));
181
182   }
183
184   /**
185    * Tests for the method that returns a dataset sequence position (base 1) for
186    * an aligned column position (base 0).
187    */
188   @Test
189   public void testFindPosition()
190   {
191     SequenceI seq = new Sequence("test", "ABCDEF");
192     assertEquals(1, seq.findPosition(0));
193     assertEquals(6, seq.findPosition(5));
194     // assertEquals(-1, seq.findPosition(6)); // fails
195
196     seq = new Sequence("test", "AB-C-D--");
197     assertEquals(1, seq.findPosition(0));
198     assertEquals(2, seq.findPosition(1));
199     // gap position 'finds' residue to the right (not the left as per javadoc)
200     assertEquals(3, seq.findPosition(2));
201     assertEquals(3, seq.findPosition(3));
202     assertEquals(4, seq.findPosition(4));
203     assertEquals(4, seq.findPosition(5));
204     // returns 1 more than sequence length if off the end ?!?
205     assertEquals(5, seq.findPosition(6));
206     assertEquals(5, seq.findPosition(7));
207
208     seq = new Sequence("test", "--AB-C-DEF--");
209     assertEquals(1, seq.findPosition(0));
210     assertEquals(1, seq.findPosition(1));
211     assertEquals(1, seq.findPosition(2));
212     assertEquals(2, seq.findPosition(3));
213     assertEquals(3, seq.findPosition(4));
214     assertEquals(3, seq.findPosition(5));
215     assertEquals(4, seq.findPosition(6));
216     assertEquals(4, seq.findPosition(7));
217     assertEquals(5, seq.findPosition(8));
218     assertEquals(6, seq.findPosition(9));
219     assertEquals(7, seq.findPosition(10));
220     assertEquals(7, seq.findPosition(11));
221   }
222
223   @Test
224   public void testDeleteChars()
225   {
226     SequenceI seq = new Sequence("test", "ABCDEF");
227     assertEquals(1, seq.getStart());
228     assertEquals(6, seq.getEnd());
229     seq.deleteChars(2, 3);
230     assertEquals("ABDEF", seq.getSequenceAsString());
231     assertEquals(1, seq.getStart());
232     assertEquals(5, seq.getEnd());
233
234     seq = new Sequence("test", "ABCDEF");
235     seq.deleteChars(0, 2);
236     assertEquals("CDEF", seq.getSequenceAsString());
237     assertEquals(3, seq.getStart());
238     assertEquals(6, seq.getEnd());
239   }
240
241   @Test
242   public void testInsertCharAt()
243   {
244     // non-static methods:
245     SequenceI seq = new Sequence("test", "ABCDEF");
246     seq.insertCharAt(0, 'z');
247     assertEquals("zABCDEF", seq.getSequenceAsString());
248     seq.insertCharAt(2, 2, 'x');
249     assertEquals("zAxxBCDEF", seq.getSequenceAsString());
250
251     // for static method see StringUtilsTest
252   }
253
254   /**
255    * Test the method that returns an array of aligned sequence positions where
256    * the array index is the data sequence position (both base 0).
257    */
258   @Test
259   public void testGapMap()
260   {
261     SequenceI seq = new Sequence("test", "-A--B-CD-E--F-");
262     seq.createDatasetSequence();
263     assertEquals("[1, 4, 6, 7, 9, 12]", Arrays.toString(seq.gapMap()));
264   }
265
266   /**
267    * Test the method that gets sequence features, either from the sequence or
268    * its dataset.
269    */
270   @Test
271   public void testGetSequenceFeatures()
272   {
273     SequenceI seq = new Sequence("test", "GATCAT");
274     seq.createDatasetSequence();
275
276     assertNull(seq.getSequenceFeatures());
277
278     /*
279      * SequenceFeature on sequence
280      */
281     SequenceFeature sf = new SequenceFeature();
282     seq.addSequenceFeature(sf);
283     SequenceFeature[] sfs = seq.getSequenceFeatures();
284     assertEquals(1, sfs.length);
285     assertSame(sf, sfs[0]);
286
287     /*
288      * SequenceFeature on sequence and dataset sequence; returns that on
289      * sequence
290      */
291     SequenceFeature sf2 = new SequenceFeature();
292     seq.getDatasetSequence().addSequenceFeature(sf2);
293     sfs = seq.getSequenceFeatures();
294     assertEquals(1, sfs.length);
295     assertSame(sf, sfs[0]);
296
297     /*
298      * SequenceFeature on dataset sequence only
299      */
300     seq.setSequenceFeatures(null);
301     sfs = seq.getSequenceFeatures();
302     assertEquals(1, sfs.length);
303     assertSame(sf2, sfs[0]);
304
305     /*
306      * Corrupt case - no SequenceFeature, dataset's dataset is the original
307      * sequence. Test shows no infinite loop results.
308      */
309     seq.getDatasetSequence().setSequenceFeatures(null);
310     seq.getDatasetSequence().setDatasetSequence(seq); // loop!
311     assertNull(seq.getSequenceFeatures());
312   }
313 }