e879e33637e873b3e0e936029504daaf7fb4a465
[jalview.git] / test / jalview / datamodel / ResidueCountTest.java
1 package jalview.datamodel;
2
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertTrue;
6
7 import jalview.datamodel.ResidueCount;
8 import jalview.datamodel.ResidueCount.SymbolCounts;
9
10 import org.junit.Assert;
11 import org.testng.annotations.Test;
12
13 public class ResidueCountTest
14 {
15   /**
16    * Test a mix of add and put for nucleotide counting
17    */
18   @Test(groups = "Functional")
19   public void test_countNucleotide()
20   {
21     ResidueCount rc = new ResidueCount(true);
22     assertEquals(rc.getCount('A'), 0);
23     assertEquals(rc.getGapCount(), 0);
24     // add then add
25     assertEquals(rc.add('A'), 1);
26     assertEquals(rc.add('a'), 2);
27     // put then add
28     rc.put('g', 3);
29     assertEquals(rc.add('G'), 4);
30     // add then put
31     assertEquals(rc.add('c'), 1);
32     rc.put('C', 4);
33     assertEquals(rc.add('N'), 1);
34
35     assertEquals(rc.getCount('a'), 2);
36     assertEquals(rc.getCount('A'), 2);
37     assertEquals(rc.getCount('G'), 4);
38     assertEquals(rc.getCount('c'), 4);
39     assertEquals(rc.getCount('T'), 0); // never seen
40     assertEquals(rc.getCount('N'), 1);
41     assertEquals(rc.getCount('?'), 0);
42     assertEquals(rc.getCount('-'), 0);
43
44     assertFalse(rc.isCountingInts());
45     assertFalse(rc.isUsingOtherData());
46   }
47
48   /**
49    * Test adding to gap count (either using addGap or add)
50    */
51   @Test(groups = "Functional")
52   public void testAddGap()
53   {
54     ResidueCount rc = new ResidueCount(true);
55     rc.addGap();
56     rc.add('-');
57     rc.add('.');
58     rc.add(' ');
59     
60     assertEquals(rc.getGapCount(), 4);
61     assertEquals(rc.getCount(' '), 4);
62     assertEquals(rc.getCount('-'), 4);
63     assertEquals(rc.getCount('.'), 4);
64     assertFalse(rc.isUsingOtherData());
65     assertFalse(rc.isCountingInts());
66   }
67
68   @Test(groups = "Functional")
69   public void testOverflow()
70   {
71     /*
72      * overflow from add
73      */
74     ResidueCount rc = new ResidueCount(true);
75     rc.addGap();
76     rc.put('A', Short.MAX_VALUE - 1);
77     assertFalse(rc.isCountingInts());
78     rc.add('A');
79     assertFalse(rc.isCountingInts());
80     rc.add('A');
81     assertTrue(rc.isCountingInts());
82     assertEquals(rc.getCount('a'), Short.MAX_VALUE + 1);
83     rc.add('A');
84     assertTrue(rc.isCountingInts());
85     assertEquals(rc.getCount('a'), Short.MAX_VALUE + 2);
86     assertEquals(rc.getGapCount(), 1);
87     rc.addGap();
88     assertEquals(rc.getGapCount(), 2);
89
90     /*
91      * overflow from put
92      */
93     rc = new ResidueCount(true);
94     rc.put('G', Short.MAX_VALUE + 1);
95     assertTrue(rc.isCountingInts());
96     assertEquals(rc.getCount('g'), Short.MAX_VALUE + 1);
97     rc.put('G', 1);
98     assertTrue(rc.isCountingInts());
99     assertEquals(rc.getCount('g'), 1);
100
101     /*
102      * underflow from put
103      */
104     rc = new ResidueCount(true);
105     rc.put('G', Short.MIN_VALUE - 1);
106     assertTrue(rc.isCountingInts());
107     assertEquals(rc.getCount('g'), Short.MIN_VALUE - 1);
108   }
109
110   /**
111    * Test a mix of add and put for peptide counting
112    */
113   @Test(groups = "Functional")
114   public void test_countPeptide()
115   {
116     ResidueCount rc = new ResidueCount(false);
117     rc.put('q', 4);
118     rc.add('Q');
119     rc.add('X');
120     rc.add('x');
121     rc.add('W');
122     rc.put('w', 7);
123     rc.put('m', 12);
124     rc.put('M', 13);
125
126     assertEquals(rc.getCount('q'), 5);
127     assertEquals(rc.getCount('X'), 2);
128     assertEquals(rc.getCount('W'), 7);
129     assertEquals(rc.getCount('m'), 13);
130     assertEquals(rc.getCount('G'), 0);
131     assertEquals(rc.getCount('-'), 0);
132
133     assertFalse(rc.isCountingInts());
134     assertFalse(rc.isUsingOtherData());
135   }
136
137   @Test(groups = "Functional")
138   public void test_unexpectedPeptide()
139   {
140     ResidueCount rc = new ResidueCount(false);
141     // expected characters (upper or lower case):
142     String aas = "ACDEFGHIKLMNPQRSTVWXY";
143     String lower = aas.toLowerCase();
144     for (int i = 0; i < aas.length(); i++)
145     {
146       rc.put(aas.charAt(i), i);
147       rc.add(lower.charAt(i));
148     }
149     for (int i = 0; i < aas.length(); i++)
150     {
151       assertEquals(rc.getCount(aas.charAt(i)), i + 1);
152     }
153     assertFalse(rc.isUsingOtherData());
154
155     rc.put('J', 4);
156     assertTrue(rc.isUsingOtherData());
157     assertEquals(rc.getCount('J'), 4);
158     rc.add('j');
159     assertEquals(rc.getCount('J'), 5);
160   }
161
162   @Test(groups = "Functional")
163   public void test_unexpectedNucleotide()
164   {
165     ResidueCount rc = new ResidueCount(true);
166     // expected characters (upper or lower case):
167     String nucs = "ACGTUN";
168     String lower = nucs.toLowerCase();
169     for (int i = 0; i < nucs.length(); i++)
170     {
171       rc.put(nucs.charAt(i), i);
172       rc.add(lower.charAt(i));
173     }
174     for (int i = 0; i < nucs.length(); i++)
175     {
176       assertEquals(rc.getCount(nucs.charAt(i)), i + 1);
177     }
178     assertFalse(rc.isUsingOtherData());
179
180     rc.add('J');
181     assertTrue(rc.isUsingOtherData());
182   }
183
184   @Test(groups = "Functional")
185   public void testGetModalCount()
186   {
187     ResidueCount rc = new ResidueCount(true);
188     rc.add('c');
189     rc.add('g');
190     rc.add('c');
191     assertEquals(rc.getModalCount(), 2);
192
193     // modal count is in the 'short overflow' counts
194     rc = new ResidueCount();
195     rc.add('c');
196     rc.put('g', Short.MAX_VALUE);
197     rc.add('G');
198     assertEquals(rc.getModalCount(), Short.MAX_VALUE + 1);
199
200     // modal count is in the 'other data' counts
201     rc = new ResidueCount(false);
202     rc.add('Q');
203     rc.add('{');
204     rc.add('{');
205     assertEquals(rc.getModalCount(), 2);
206
207     // verify modal count excludes gap
208     rc = new ResidueCount();
209     rc.add('Q');
210     rc.add('P');
211     rc.add('Q');
212     rc.addGap();
213     rc.addGap();
214     rc.addGap();
215     assertEquals(rc.getModalCount(), 2);
216   }
217
218   @Test(groups = "Functional")
219   public void testGetResiduesForCount()
220   {
221     ResidueCount rc = new ResidueCount(true);
222     rc.add('c');
223     rc.add('g');
224     rc.add('c');
225     assertEquals(rc.getResiduesForCount(2), "C");
226     assertEquals(rc.getResiduesForCount(1), "G");
227     assertEquals(rc.getResiduesForCount(3), "");
228     assertEquals(rc.getResiduesForCount(0), "");
229     assertEquals(rc.getResiduesForCount(-1), "");
230
231     // modal count is in the 'short overflow' counts
232     rc = new ResidueCount(true);
233     rc.add('c');
234     rc.put('g', Short.MAX_VALUE);
235     rc.add('G');
236     assertEquals(rc.getResiduesForCount(Short.MAX_VALUE + 1), "G");
237     assertEquals(rc.getResiduesForCount(1), "C");
238
239     // peptide modal count is in the 'short overflow' counts
240     rc = new ResidueCount(false);
241     rc.add('c');
242     rc.put('p', Short.MAX_VALUE);
243     rc.add('P');
244     assertEquals(rc.getResiduesForCount(Short.MAX_VALUE + 1), "P");
245     assertEquals(rc.getResiduesForCount(1), "C");
246   
247     // modal count is in the 'other data' counts
248     rc = new ResidueCount();
249     rc.add('Q');
250     rc.add('{');
251     rc.add('{');
252     assertEquals(rc.getResiduesForCount(1), "Q");
253     assertEquals(rc.getResiduesForCount(2), "{");
254
255     // residues share modal count
256     rc = new ResidueCount();
257     rc.add('G');
258     rc.add('G');
259     rc.add('c');
260     rc.add('C');
261     rc.add('U');
262     assertEquals(rc.getResiduesForCount(1), "U");
263     assertEquals(rc.getResiduesForCount(2), "CG");
264
265     // expected and unexpected symbols share modal count
266     rc = new ResidueCount();
267     rc.add('G');
268     rc.add('t');
269     rc.add('[');
270     rc.add('[');
271     rc.add('t');
272     rc.add('G');
273     rc.add('c');
274     rc.add('C');
275     rc.add('U');
276     assertEquals(rc.getResiduesForCount(1), "U");
277     assertEquals(rc.getResiduesForCount(2), "CGT[");
278   }
279
280   @Test(groups = "Functional")
281   public void testGetSymbolCounts_nucleotide()
282   {
283     ResidueCount rc = new ResidueCount(true);
284     rc.add('g');
285     rc.add('c');
286     rc.add('G');
287     rc.add('J'); // 'otherData'
288     rc.add('g');
289     rc.add('N');
290     rc.put('[', 0); // 'otherdata'
291
292     SymbolCounts sc = rc.getSymbolCounts();
293     Assert.assertArrayEquals(new char[] { 'C', 'G', 'N', 'J', '[' },
294             sc.symbols);
295     Assert.assertArrayEquals(new int[] { 1, 3, 1, 1, 0 }, sc.values);
296
297     // now with overflow to int counts
298     rc.put('U', Short.MAX_VALUE);
299     rc.add('u');
300     sc = rc.getSymbolCounts();
301     Assert.assertArrayEquals(new char[] { 'C', 'G', 'N', 'U', 'J', '[' },
302             sc.symbols);
303     Assert.assertArrayEquals(new int[] { 1, 3, 1, 32768, 1, 0 }, sc.values);
304   }
305
306   @Test(groups = "Functional")
307   public void testGetSymbolCounts_peptide()
308   {
309     ResidueCount rc = new ResidueCount(false);
310     rc.add('W');
311     rc.add('q');
312     rc.add('W');
313     rc.add('Z'); // 'otherData'
314     rc.add('w');
315     rc.add('L');
316
317     SymbolCounts sc = rc.getSymbolCounts();
318     Assert.assertArrayEquals(new char[] { 'L', 'Q', 'W', 'Z' }, sc.symbols);
319     Assert.assertArrayEquals(new int[] { 1, 1, 3, 1 }, sc.values);
320
321     // now with overflow to int counts
322     rc.put('W', Short.MAX_VALUE);
323     rc.add('W');
324     sc = rc.getSymbolCounts();
325     Assert.assertArrayEquals(new char[] { 'L', 'Q', 'W', 'Z' }, sc.symbols);
326     Assert.assertArrayEquals(new int[] { 1, 1, 32768, 1 }, sc.values);
327   }
328
329   @Test(groups = "Functional")
330   public void testToString()
331   {
332     ResidueCount rc = new ResidueCount();
333     rc.add('q');
334     rc.add('c');
335     rc.add('Q');
336     assertEquals(rc.toString(), "[ C:1 Q:2 ]");
337
338     // add 'other data'
339     rc.add('{');
340     assertEquals(rc.toString(), "[ C:1 Q:2 {:1 ]");
341
342     // switch from short to int counting:
343     rc.put('G', Short.MAX_VALUE);
344     rc.add('g');
345     assertEquals(rc.toString(), "[ C:1 G:32768 Q:2 {:1 ]");
346   }
347
348   @Test(groups = "Functional")
349   public void testGetTooltip()
350   {
351     ResidueCount rc = new ResidueCount();
352
353     // no counts!
354     assertEquals(rc.getTooltip(20, 1), "");
355
356     /*
357      * count 7 C, 6 K, 7 Q, 10 P, 9 W, 1 F (total 40)
358      */
359     for (int i = 0; i < 7; i++)
360     {
361       rc.add('c');
362       rc.add('q');
363     }
364     for (int i = 0; i < 10; i++)
365     {
366       rc.add('p');
367     }
368     for (int i = 0; i < 9; i++)
369     {
370       rc.add('W');
371     }
372     for (int i = 0; i < 6; i++)
373     {
374       rc.add('K');
375     }
376     rc.add('F');
377     
378     assertEquals(rc.getTooltip(40, 0),
379             "P 25%; W 22%; C 17%; Q 17%; K 15%; F 2%");
380
381     assertEquals(rc.getTooltip(30, 1),
382             "P 33.3%; W 30.0%; C 23.3%; Q 23.3%; K 20.0%; F 3.3%");
383   }
384
385   @Test(groups = "Functional")
386   public void testPut()
387   {
388     ResidueCount rc = new ResidueCount();
389     rc.put('q', 3);
390     assertEquals(rc.getCount('Q'), 3);
391     rc.put(' ', 4);
392     assertEquals(rc.getGapCount(), 4);
393     rc.put('.', 5);
394     assertEquals(rc.getGapCount(), 5);
395     rc.put('-', 6);
396     assertEquals(rc.getGapCount(), 6);
397
398     rc.put('?', 5);
399     assertEquals(rc.getCount('?'), 5);
400     rc.put('?', 6);
401     rc.put('!', 7);
402     assertEquals(rc.getCount('?'), 6);
403     assertEquals(rc.getCount('!'), 7);
404   }
405 }