Clover icon

Coverage Report

  1. Project Clover database Tue Mar 10 2026 14:58:44 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
0.00%
 

Contributing tests

No tests hitting this source file were found.

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