Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.datamodel

File ResidueCountTest.java

 

Code metrics

16
269
15
1
480
363
23
0.09
17.93
15
1.53

Classes

Class Line # Actions
ResidueCountTest 38 269 23
1.0100%
 

Contributing tests

This file is covered by 14 tests. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.datamodel;
22   
23    import java.util.Locale;
24   
25    import static org.testng.Assert.assertEquals;
26    import static org.testng.Assert.assertFalse;
27    import static org.testng.Assert.assertTrue;
28   
29    import jalview.datamodel.ResidueCount.SymbolCounts;
30    import jalview.gui.JvOptionPane;
31   
32    import java.util.Arrays;
33   
34    import org.junit.Assert;
35    import org.testng.annotations.BeforeClass;
36    import org.testng.annotations.Test;
37   
 
38    public class ResidueCountTest
39    {
40   
 
41  1 toggle @BeforeClass(alwaysRun = true)
42    public void setUpJvOptionPane()
43    {
44  1 JvOptionPane.setInteractiveMode(false);
45  1 JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
46    }
47   
48    /**
49    * Test a mix of add and put for nucleotide counting
50    */
 
51  1 toggle @Test(groups = "Functional")
52    public void test_countNucleotide()
53    {
54  1 ResidueCount rc = new ResidueCount(true);
55  1 assertEquals(rc.getCount('A'), 0);
56  1 assertEquals(rc.getGapCount(), 0);
57    // add then add
58  1 assertEquals(rc.add('A'), 1);
59  1 assertEquals(rc.add('a'), 2);
60    // put then add
61  1 rc.put('g', 3);
62  1 assertEquals(rc.add('G'), 4);
63    // add then put
64  1 assertEquals(rc.add('c'), 1);
65  1 rc.put('C', 4);
66  1 assertEquals(rc.add('N'), 1);
67   
68  1 assertEquals(rc.getCount('a'), 2);
69  1 assertEquals(rc.getCount('A'), 2);
70  1 assertEquals(rc.getCount('G'), 4);
71  1 assertEquals(rc.getCount('c'), 4);
72  1 assertEquals(rc.getCount('T'), 0); // never seen
73  1 assertEquals(rc.getCount('N'), 1);
74  1 assertEquals(rc.getCount('?'), 0);
75  1 assertEquals(rc.getCount('-'), 0);
76  1 assertEquals(rc.getTotalResidueCount(), 11);
77   
78  1 assertFalse(rc.isCountingInts());
79  1 assertFalse(rc.isUsingOtherData());
80    }
81   
82    /**
83    * Test adding to gap count (either using addGap or add)
84    */
 
85  1 toggle @Test(groups = "Functional")
86    public void testAddGap()
87    {
88  1 ResidueCount rc = new ResidueCount(true);
89  1 rc.addGap();
90  1 rc.add('-');
91  1 rc.add('.');
92  1 rc.add(' ');
93   
94  1 assertEquals(rc.getGapCount(), 4);
95  1 assertEquals(rc.getCount(' '), 4);
96  1 assertEquals(rc.getCount('-'), 4);
97  1 assertEquals(rc.getCount('.'), 4);
98  1 assertEquals(rc.getTotalResidueCount(), 0);
99  1 assertFalse(rc.isUsingOtherData());
100  1 assertFalse(rc.isCountingInts());
101   
102  1 rc.set(ResidueCount.GAP_COUNT, Short.MAX_VALUE - 2);
103  1 assertEquals(rc.getGapCount(), Short.MAX_VALUE - 2);
104  1 assertFalse(rc.isCountingInts());
105  1 rc.addGap();
106  1 assertEquals(rc.getGapCount(), Short.MAX_VALUE - 1);
107  1 assertFalse(rc.isCountingInts());
108  1 rc.addGap();
109  1 assertEquals(rc.getGapCount(), Short.MAX_VALUE);
110  1 rc.addGap();
111  1 assertTrue(rc.isCountingInts());
112  1 assertEquals(rc.getGapCount(), Short.MAX_VALUE + 1);
113    }
114   
 
115  1 toggle @Test(groups = "Functional")
116    public void testOverflow()
117    {
118    /*
119    * overflow from add
120    */
121  1 ResidueCount rc = new ResidueCount(true);
122  1 rc.addGap();
123  1 rc.put('A', Short.MAX_VALUE - 1);
124  1 assertFalse(rc.isCountingInts());
125  1 rc.add('A');
126  1 assertFalse(rc.isCountingInts());
127  1 rc.add('A');
128  1 assertTrue(rc.isCountingInts());
129  1 assertEquals(rc.getCount('a'), Short.MAX_VALUE + 1);
130  1 rc.add('A');
131  1 assertTrue(rc.isCountingInts());
132  1 assertEquals(rc.getCount('a'), Short.MAX_VALUE + 2);
133  1 assertEquals(rc.getGapCount(), 1);
134  1 rc.addGap();
135  1 assertEquals(rc.getGapCount(), 2);
136   
137    /*
138    * overflow from put
139    */
140  1 rc = new ResidueCount(true);
141  1 rc.put('G', Short.MAX_VALUE + 1);
142  1 assertTrue(rc.isCountingInts());
143  1 assertEquals(rc.getCount('g'), Short.MAX_VALUE + 1);
144  1 rc.put('G', 1);
145  1 assertTrue(rc.isCountingInts());
146  1 assertEquals(rc.getCount('g'), 1);
147   
148    /*
149    * underflow from put
150    */
151  1 rc = new ResidueCount(true);
152  1 rc.put('G', Short.MIN_VALUE - 1);
153  1 assertTrue(rc.isCountingInts());
154  1 assertEquals(rc.getCount('g'), Short.MIN_VALUE - 1);
155    }
156   
157    /**
158    * Test a mix of add and put for peptide counting
159    */
 
160  1 toggle @Test(groups = "Functional")
161    public void test_countPeptide()
162    {
163  1 ResidueCount rc = new ResidueCount(false);
164  1 rc.put('q', 4);
165  1 rc.add('Q');
166  1 rc.add('X');
167  1 rc.add('x');
168  1 rc.add('W');
169  1 rc.put('w', 7);
170  1 rc.put('m', 12);
171  1 rc.put('M', 13);
172   
173  1 assertEquals(rc.getCount('q'), 5);
174  1 assertEquals(rc.getCount('X'), 2);
175  1 assertEquals(rc.getCount('W'), 7);
176  1 assertEquals(rc.getCount('m'), 13);
177  1 assertEquals(rc.getCount('G'), 0);
178  1 assertEquals(rc.getCount('-'), 0);
179  1 assertEquals(rc.getTotalResidueCount(), 27);
180   
181  1 assertFalse(rc.isCountingInts());
182  1 assertFalse(rc.isUsingOtherData());
183    }
184   
 
185  1 toggle @Test(groups = "Functional")
186    public void test_unexpectedPeptide()
187    {
188  1 ResidueCount rc = new ResidueCount(false);
189    // expected characters (upper or lower case):
190  1 String aas = "ACDEFGHIKLMNPQRSTVWXY";
191  1 String lower = aas.toLowerCase(Locale.ROOT);
192  22 for (int i = 0; i < aas.length(); i++)
193    {
194  21 rc.put(aas.charAt(i), i);
195  21 rc.add(lower.charAt(i));
196    }
197  22 for (int i = 0; i < aas.length(); i++)
198    {
199  21 assertEquals(rc.getCount(aas.charAt(i)), i + 1);
200    }
201  1 assertFalse(rc.isUsingOtherData());
202   
203  1 rc.put('J', 4);
204  1 assertTrue(rc.isUsingOtherData());
205  1 assertEquals(rc.getCount('J'), 4);
206  1 rc.add('j');
207  1 assertEquals(rc.getCount('J'), 5);
208    }
209   
 
210  1 toggle @Test(groups = "Functional")
211    public void test_unexpectedNucleotide()
212    {
213  1 ResidueCount rc = new ResidueCount(true);
214    // expected characters (upper or lower case):
215  1 String nucs = "ACGTUN";
216  1 String lower = nucs.toLowerCase(Locale.ROOT);
217  7 for (int i = 0; i < nucs.length(); i++)
218    {
219  6 rc.put(nucs.charAt(i), i);
220  6 rc.add(lower.charAt(i));
221    }
222  7 for (int i = 0; i < nucs.length(); i++)
223    {
224  6 assertEquals(rc.getCount(nucs.charAt(i)), i + 1);
225    }
226  1 assertFalse(rc.isUsingOtherData());
227   
228  1 rc.add('J');
229  1 assertTrue(rc.isUsingOtherData());
230    }
231   
 
232  1 toggle @Test(groups = "Functional")
233    public void testGetModalCount()
234    {
235  1 ResidueCount rc = new ResidueCount(true);
236  1 rc.add('c');
237  1 rc.add('g');
238  1 rc.add('c');
239  1 assertEquals(rc.getModalCount(), 2);
240   
241    // modal count is in the 'short overflow' counts
242  1 rc = new ResidueCount();
243  1 rc.add('c');
244  1 rc.put('g', Short.MAX_VALUE);
245  1 rc.add('G');
246  1 assertEquals(rc.getModalCount(), Short.MAX_VALUE + 1);
247   
248    // modal count is in the 'other data' counts
249  1 rc = new ResidueCount(false);
250  1 rc.add('Q');
251  1 rc.add('{');
252  1 rc.add('{');
253  1 assertEquals(rc.getModalCount(), 2);
254   
255    // verify modal count excludes gap
256  1 rc = new ResidueCount();
257  1 rc.add('Q');
258  1 rc.add('P');
259  1 rc.add('Q');
260  1 rc.addGap();
261  1 rc.addGap();
262  1 rc.addGap();
263  1 assertEquals(rc.getModalCount(), 2);
264    }
265   
 
266  1 toggle @Test(groups = "Functional")
267    public void testGetResiduesForCount()
268    {
269  1 ResidueCount rc = new ResidueCount(true);
270  1 rc.add('c');
271  1 rc.add('g');
272  1 rc.add('c');
273  1 assertEquals(rc.getResiduesForCount(2), "C");
274  1 assertEquals(rc.getResiduesForCount(1), "G");
275  1 assertEquals(rc.getResiduesForCount(3), "");
276  1 assertEquals(rc.getResiduesForCount(0), "");
277  1 assertEquals(rc.getResiduesForCount(-1), "");
278   
279    // modal count is in the 'short overflow' counts
280  1 rc = new ResidueCount(true);
281  1 rc.add('c');
282  1 rc.put('g', Short.MAX_VALUE);
283  1 rc.add('G');
284  1 assertEquals(rc.getResiduesForCount(Short.MAX_VALUE + 1), "G");
285  1 assertEquals(rc.getResiduesForCount(1), "C");
286   
287    // peptide modal count is in the 'short overflow' counts
288  1 rc = new ResidueCount(false);
289  1 rc.add('c');
290  1 rc.put('p', Short.MAX_VALUE);
291  1 rc.add('P');
292  1 assertEquals(rc.getResiduesForCount(Short.MAX_VALUE + 1), "P");
293  1 assertEquals(rc.getResiduesForCount(1), "C");
294   
295    // modal count is in the 'other data' counts
296  1 rc = new ResidueCount();
297  1 rc.add('Q');
298  1 rc.add('{');
299  1 rc.add('{');
300  1 assertEquals(rc.getResiduesForCount(1), "Q");
301  1 assertEquals(rc.getResiduesForCount(2), "{");
302   
303    // residues share modal count
304  1 rc = new ResidueCount();
305  1 rc.add('G');
306  1 rc.add('G');
307  1 rc.add('c');
308  1 rc.add('C');
309  1 rc.add('U');
310  1 assertEquals(rc.getResiduesForCount(1), "U");
311  1 assertEquals(rc.getResiduesForCount(2), "CG");
312   
313    // expected and unexpected symbols share modal count
314  1 rc = new ResidueCount();
315  1 rc.add('G');
316  1 rc.add('t');
317  1 rc.add('[');
318  1 rc.add('[');
319  1 rc.add('t');
320  1 rc.add('G');
321  1 rc.add('c');
322  1 rc.add('C');
323  1 rc.add('U');
324  1 assertEquals(rc.getResiduesForCount(1), "U");
325  1 assertEquals(rc.getResiduesForCount(2), "CGT[");
326    }
327   
 
328  1 toggle @Test(groups = "Functional")
329    public void testGetSymbolCounts_nucleotide()
330    {
331  1 ResidueCount rc = new ResidueCount(true);
332  1 rc.add('g');
333  1 rc.add('c');
334  1 rc.add('G');
335  1 rc.add('J'); // 'otherData'
336  1 rc.add('g');
337  1 rc.add('N');
338  1 rc.put('[', 0); // 'otherdata'
339   
340  1 SymbolCounts sc = rc.getSymbolCounts();
341  1 Assert.assertArrayEquals(new char[] { 'C', 'G', 'N', 'J', '[' },
342    sc.symbols);
343  1 Assert.assertArrayEquals(new int[] { 1, 3, 1, 1, 0 }, sc.values);
344   
345    // now with overflow to int counts
346  1 rc.put('U', Short.MAX_VALUE);
347  1 rc.add('u');
348  1 sc = rc.getSymbolCounts();
349  1 Assert.assertArrayEquals(new char[] { 'C', 'G', 'N', 'U', 'J', '[' },
350    sc.symbols);
351  1 Assert.assertArrayEquals(new int[] { 1, 3, 1, 32768, 1, 0 }, sc.values);
352    }
353   
 
354  1 toggle @Test(groups = "Functional")
355    public void testGetSymbolCounts_peptide()
356    {
357  1 ResidueCount rc = new ResidueCount(false);
358  1 rc.add('W');
359  1 rc.add('q');
360  1 rc.add('W');
361  1 rc.add('Z'); // 'otherData'
362  1 rc.add('w');
363  1 rc.add('L');
364   
365  1 SymbolCounts sc = rc.getSymbolCounts();
366  1 Assert.assertArrayEquals(new char[] { 'L', 'Q', 'W', 'Z' }, sc.symbols);
367  1 Assert.assertArrayEquals(new int[] { 1, 1, 3, 1 }, sc.values);
368   
369    // now with overflow to int counts
370  1 rc.put('W', Short.MAX_VALUE);
371  1 rc.add('W');
372  1 sc = rc.getSymbolCounts();
373  1 Assert.assertArrayEquals(new char[] { 'L', 'Q', 'W', 'Z' }, sc.symbols);
374  1 Assert.assertArrayEquals(new int[] { 1, 1, 32768, 1 }, sc.values);
375    }
376   
 
377  1 toggle @Test(groups = "Functional")
378    public void testToString()
379    {
380  1 ResidueCount rc = new ResidueCount();
381  1 rc.add('q');
382  1 rc.add('c');
383  1 rc.add('Q');
384  1 assertEquals(rc.toString(), "[ C:1 Q:2 ]");
385   
386    // add 'other data'
387  1 rc.add('{');
388  1 assertEquals(rc.toString(), "[ C:1 Q:2 {:1 ]");
389   
390    // switch from short to int counting:
391  1 rc.put('G', Short.MAX_VALUE);
392  1 rc.add('g');
393  1 assertEquals(rc.toString(), "[ C:1 G:32768 Q:2 {:1 ]");
394    }
395   
 
396  1 toggle @Test(groups = "Functional")
397    public void testGetTooltip()
398    {
399  1 ResidueCount rc = new ResidueCount();
400   
401    // no counts!
402  1 assertEquals(rc.getTooltip(20, 1), "");
403   
404    /*
405    * count 7 C, 6 K, 7 Q, 10 P, 9 W, 1 F (total 40)
406    */
407  8 for (int i = 0; i < 7; i++)
408    {
409  7 rc.add('c');
410  7 rc.add('q');
411    }
412  11 for (int i = 0; i < 10; i++)
413    {
414  10 rc.add('p');
415    }
416  10 for (int i = 0; i < 9; i++)
417    {
418  9 rc.add('W');
419    }
420  7 for (int i = 0; i < 6; i++)
421    {
422  6 rc.add('K');
423    }
424  1 rc.add('F');
425   
426    /*
427    * percentages are rounded (0.5 rounded up)
428    * 10/40 9/40 7/40 6/40 1/40
429    */
430  1 assertEquals(rc.getTooltip(40, 0),
431    "P 25%; W 23%; C 18%; Q 18%; K 15%; F 3%");
432   
433  1 rc.add('Q');
434    /*
435    * 10/30 9/30 8/30 7/30 6/30 1/30
436    */
437  1 assertEquals(rc.getTooltip(30, 1),
438    "P 33.3%; W 30.0%; Q 26.7%; C 23.3%; K 20.0%; F 3.3%");
439    }
440   
 
441  1 toggle @Test(groups = "Functional")
442    public void testPut()
443    {
444  1 ResidueCount rc = new ResidueCount();
445  1 rc.put('q', 3);
446  1 assertEquals(rc.getCount('Q'), 3);
447  1 rc.put(' ', 4);
448  1 assertEquals(rc.getGapCount(), 4);
449  1 rc.put('.', 5);
450  1 assertEquals(rc.getGapCount(), 5);
451  1 rc.put('-', 6);
452  1 assertEquals(rc.getGapCount(), 6);
453   
454  1 rc.put('?', 5);
455  1 assertEquals(rc.getCount('?'), 5);
456  1 rc.put('?', 6);
457  1 rc.put('!', 7);
458  1 assertEquals(rc.getCount('?'), 6);
459  1 assertEquals(rc.getCount('!'), 7);
460    }
461   
 
462  1 toggle @Test(groups = "Functional")
463    public void testConstructor_forSequences()
464    {
465  1 SequenceI seq1 = new Sequence("seq1", "abcde--. FCD");
466  1 SequenceI seq2 = new Sequence("seq2", "ab.kKqBd-.");
467  1 ResidueCount rc = new ResidueCount(Arrays.asList(seq1, seq2));
468   
469  1 assertEquals(rc.getGapCount(), 7);
470  1 assertEquals(rc.getTotalResidueCount(), 15); // excludes gaps
471  1 assertEquals(rc.getCount('a'), 2);
472  1 assertEquals(rc.getCount('A'), 2);
473  1 assertEquals(rc.getCount('B'), 3);
474  1 assertEquals(rc.getCount('c'), 2);
475  1 assertEquals(rc.getCount('D'), 3);
476  1 assertEquals(rc.getCount('f'), 1);
477  1 assertEquals(rc.getCount('K'), 2);
478  1 assertEquals(rc.getCount('Q'), 1);
479    }
480    }