JAL-98 use Profile to store consensus, ResidueCount for fast compact
[jalview.git] / test / jalview / analysis / ResidueCountTest.java
1 package jalview.analysis;
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.analysis.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.put('A', Short.MAX_VALUE - 1);
75     assertFalse(rc.isCountingInts());
76     rc.add('A');
77     assertFalse(rc.isCountingInts());
78     rc.add('A');
79     assertTrue(rc.isCountingInts());
80     assertEquals(rc.getCount('a'), Short.MAX_VALUE + 1);
81
82     /*
83      * overflow from put
84      */
85     rc = new ResidueCount(true);
86     rc.put('G', Short.MAX_VALUE + 1);
87     assertTrue(rc.isCountingInts());
88     assertEquals(rc.getCount('g'), Short.MAX_VALUE + 1);
89   }
90
91   /**
92    * Test a mix of add and put for peptide counting
93    */
94   @Test(groups = "Functional")
95   public void test_countPeptide()
96   {
97     ResidueCount rc = new ResidueCount(false);
98     rc.put('q', 4);
99     rc.add('Q');
100     rc.add('X');
101     rc.add('x');
102     rc.add('W');
103     rc.put('w', 7);
104     rc.put('m', 12);
105     rc.put('M', 13);
106
107     assertEquals(rc.getCount('q'), 5);
108     assertEquals(rc.getCount('X'), 2);
109     assertEquals(rc.getCount('W'), 7);
110     assertEquals(rc.getCount('m'), 13);
111     assertEquals(rc.getCount('G'), 0);
112     assertEquals(rc.getCount('-'), 0);
113
114     assertFalse(rc.isCountingInts());
115     assertFalse(rc.isUsingOtherData());
116   }
117
118   @Test(groups = "Functional")
119   public void test_unexpectedPeptide()
120   {
121     ResidueCount rc = new ResidueCount(false);
122     // expected characters (upper or lower case):
123     String aas = "ACDEFGHIKLMNPQRSTVWXY";
124     String lower = aas.toLowerCase();
125     for (int i = 0; i < aas.length(); i++)
126     {
127       rc.put(aas.charAt(i), i);
128       rc.add(lower.charAt(i));
129     }
130     for (int i = 0; i < aas.length(); i++)
131     {
132       assertEquals(rc.getCount(aas.charAt(i)), i + 1);
133     }
134     assertFalse(rc.isUsingOtherData());
135
136     rc.put('J', 4);
137     assertTrue(rc.isUsingOtherData());
138   }
139
140   @Test(groups = "Functional")
141   public void test_unexpectedNucleotide()
142   {
143     ResidueCount rc = new ResidueCount(true);
144     // expected characters (upper or lower case):
145     String nucs = "ACGTUN";
146     String lower = nucs.toLowerCase();
147     for (int i = 0; i < nucs.length(); i++)
148     {
149       rc.put(nucs.charAt(i), i);
150       rc.add(lower.charAt(i));
151     }
152     for (int i = 0; i < nucs.length(); i++)
153     {
154       assertEquals(rc.getCount(nucs.charAt(i)), i + 1);
155     }
156     assertFalse(rc.isUsingOtherData());
157
158     rc.add('J');
159     assertTrue(rc.isUsingOtherData());
160   }
161
162   @Test(groups = "Functional")
163   public void testGetModalCount()
164   {
165     ResidueCount rc = new ResidueCount();
166     rc.add('c');
167     rc.add('g');
168     rc.add('c');
169     assertEquals(rc.getModalCount(), 2);
170
171     // modal count is in the 'short overflow' counts
172     rc = new ResidueCount();
173     rc.add('c');
174     rc.put('g', Short.MAX_VALUE);
175     rc.add('G');
176     assertEquals(rc.getModalCount(), Short.MAX_VALUE + 1);
177
178     // modal count is in the 'other data' counts
179     rc = new ResidueCount();
180     rc.add('Q');
181     rc.add('{');
182     rc.add('{');
183     assertEquals(rc.getModalCount(), 2);
184
185     // verify modal count excludes gap
186     rc = new ResidueCount();
187     rc.add('Q');
188     rc.add('P');
189     rc.add('Q');
190     rc.addGap();
191     rc.addGap();
192     rc.addGap();
193     assertEquals(rc.getModalCount(), 2);
194   }
195
196   @Test(groups = "Functional")
197   public void testGetResiduesForCount()
198   {
199     ResidueCount rc = new ResidueCount();
200     rc.add('c');
201     rc.add('g');
202     rc.add('c');
203     assertEquals(rc.getResiduesForCount(2), "C");
204     assertEquals(rc.getResiduesForCount(1), "G");
205     assertEquals(rc.getResiduesForCount(3), "");
206     assertEquals(rc.getResiduesForCount(0), "");
207     assertEquals(rc.getResiduesForCount(-1), "");
208
209     // modal count is in the 'short overflow' counts
210     rc = new ResidueCount();
211     rc.add('c');
212     rc.put('g', Short.MAX_VALUE);
213     rc.add('G');
214     assertEquals(rc.getResiduesForCount(Short.MAX_VALUE + 1), "G");
215     assertEquals(rc.getResiduesForCount(1), "C");
216   
217     // modal count is in the 'other data' counts
218     rc = new ResidueCount();
219     rc.add('Q');
220     rc.add('{');
221     rc.add('{');
222     assertEquals(rc.getResiduesForCount(1), "Q");
223     assertEquals(rc.getResiduesForCount(2), "{");
224
225     // residues share modal count
226     rc = new ResidueCount();
227     rc.add('G');
228     rc.add('G');
229     rc.add('c');
230     rc.add('C');
231     rc.add('U');
232     assertEquals(rc.getResiduesForCount(1), "U");
233     assertEquals(rc.getResiduesForCount(2), "CG");
234
235     // expected and unexpected symbols share modal count
236     rc = new ResidueCount();
237     rc.add('G');
238     rc.add('t');
239     rc.add('[');
240     rc.add('[');
241     rc.add('t');
242     rc.add('G');
243     rc.add('c');
244     rc.add('C');
245     rc.add('U');
246     assertEquals(rc.getResiduesForCount(1), "U");
247     assertEquals(rc.getResiduesForCount(2), "CGT[");
248   }
249
250   @Test(groups = "Functional")
251   public void testGetSymbolCounts()
252   {
253     ResidueCount rc = new ResidueCount();
254     rc.add('q');
255     rc.add('c');
256     rc.add('Q');
257     rc.add('J'); // 'otherData'
258     rc.add('q');
259     rc.add('x');
260
261     SymbolCounts sc = rc.getSymbolCounts();
262     Assert.assertArrayEquals(new char[] { 'C', 'Q', 'X', 'J' }, sc.symbols);
263     Assert.assertArrayEquals(new int[] { 1, 3, 1, 1 }, sc.values);
264
265     // now with overflow to int counts
266     rc.put('g', Short.MAX_VALUE);
267     rc.add('g');
268     sc = rc.getSymbolCounts();
269     Assert.assertArrayEquals(new char[] { 'C', 'G', 'Q', 'X', 'J' },
270             sc.symbols);
271     Assert.assertArrayEquals(new int[] { 1, 32768, 3, 1, 1 }, sc.values);
272   }
273
274   @Test(groups = "Functional")
275   public void testToString()
276   {
277     ResidueCount rc = new ResidueCount();
278     rc.add('q');
279     rc.add('c');
280     rc.add('Q');
281     assertEquals(rc.toString(), "[ C:1 Q:2 ]");
282
283     // add 'other data'
284     rc.add('{');
285     assertEquals(rc.toString(), "[ C:1 Q:2 {:1 ]");
286
287     // switch from short to int counting:
288     rc.put('G', Short.MAX_VALUE);
289     rc.add('g');
290     assertEquals(rc.toString(), "[ C:1 G:32768 Q:2 {:1 ]");
291   }
292 }