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