package jalview.analysis; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import jalview.analysis.ResidueCount.SymbolCounts; import org.junit.Assert; import org.testng.annotations.Test; public class ResidueCountTest { /** * Test a mix of add and put for nucleotide counting */ @Test(groups = "Functional") public void test_countNucleotide() { ResidueCount rc = new ResidueCount(true); assertEquals(rc.getCount('A'), 0); assertEquals(rc.getGapCount(), 0); // add then add assertEquals(rc.add('A'), 1); assertEquals(rc.add('a'), 2); // put then add rc.put('g', 3); assertEquals(rc.add('G'), 4); // add then put assertEquals(rc.add('c'), 1); rc.put('C', 4); assertEquals(rc.add('N'), 1); assertEquals(rc.getCount('a'), 2); assertEquals(rc.getCount('A'), 2); assertEquals(rc.getCount('G'), 4); assertEquals(rc.getCount('c'), 4); assertEquals(rc.getCount('T'), 0); // never seen assertEquals(rc.getCount('N'), 1); assertEquals(rc.getCount('?'), 0); assertEquals(rc.getCount('-'), 0); assertFalse(rc.isCountingInts()); assertFalse(rc.isUsingOtherData()); } /** * Test adding to gap count (either using addGap or add) */ @Test(groups = "Functional") public void testAddGap() { ResidueCount rc = new ResidueCount(true); rc.addGap(); rc.add('-'); rc.add('.'); rc.add(' '); assertEquals(rc.getGapCount(), 4); assertEquals(rc.getCount(' '), 4); assertEquals(rc.getCount('-'), 4); assertEquals(rc.getCount('.'), 4); assertFalse(rc.isUsingOtherData()); assertFalse(rc.isCountingInts()); } @Test(groups = "Functional") public void testOverflow() { /* * overflow from add */ ResidueCount rc = new ResidueCount(true); rc.put('A', Short.MAX_VALUE - 1); assertFalse(rc.isCountingInts()); rc.add('A'); assertFalse(rc.isCountingInts()); rc.add('A'); assertTrue(rc.isCountingInts()); assertEquals(rc.getCount('a'), Short.MAX_VALUE + 1); /* * overflow from put */ rc = new ResidueCount(true); rc.put('G', Short.MAX_VALUE + 1); assertTrue(rc.isCountingInts()); assertEquals(rc.getCount('g'), Short.MAX_VALUE + 1); } /** * Test a mix of add and put for peptide counting */ @Test(groups = "Functional") public void test_countPeptide() { ResidueCount rc = new ResidueCount(false); rc.put('q', 4); rc.add('Q'); rc.add('X'); rc.add('x'); rc.add('W'); rc.put('w', 7); rc.put('m', 12); rc.put('M', 13); assertEquals(rc.getCount('q'), 5); assertEquals(rc.getCount('X'), 2); assertEquals(rc.getCount('W'), 7); assertEquals(rc.getCount('m'), 13); assertEquals(rc.getCount('G'), 0); assertEquals(rc.getCount('-'), 0); assertFalse(rc.isCountingInts()); assertFalse(rc.isUsingOtherData()); } @Test(groups = "Functional") public void test_unexpectedPeptide() { ResidueCount rc = new ResidueCount(false); // expected characters (upper or lower case): String aas = "ACDEFGHIKLMNPQRSTVWXY"; String lower = aas.toLowerCase(); for (int i = 0; i < aas.length(); i++) { rc.put(aas.charAt(i), i); rc.add(lower.charAt(i)); } for (int i = 0; i < aas.length(); i++) { assertEquals(rc.getCount(aas.charAt(i)), i + 1); } assertFalse(rc.isUsingOtherData()); rc.put('J', 4); assertTrue(rc.isUsingOtherData()); } @Test(groups = "Functional") public void test_unexpectedNucleotide() { ResidueCount rc = new ResidueCount(true); // expected characters (upper or lower case): String nucs = "ACGTUN"; String lower = nucs.toLowerCase(); for (int i = 0; i < nucs.length(); i++) { rc.put(nucs.charAt(i), i); rc.add(lower.charAt(i)); } for (int i = 0; i < nucs.length(); i++) { assertEquals(rc.getCount(nucs.charAt(i)), i + 1); } assertFalse(rc.isUsingOtherData()); rc.add('J'); assertTrue(rc.isUsingOtherData()); } @Test(groups = "Functional") public void testGetModalCount() { ResidueCount rc = new ResidueCount(); rc.add('c'); rc.add('g'); rc.add('c'); assertEquals(rc.getModalCount(), 2); // modal count is in the 'short overflow' counts rc = new ResidueCount(); rc.add('c'); rc.put('g', Short.MAX_VALUE); rc.add('G'); assertEquals(rc.getModalCount(), Short.MAX_VALUE + 1); // modal count is in the 'other data' counts rc = new ResidueCount(); rc.add('Q'); rc.add('{'); rc.add('{'); assertEquals(rc.getModalCount(), 2); // verify modal count excludes gap rc = new ResidueCount(); rc.add('Q'); rc.add('P'); rc.add('Q'); rc.addGap(); rc.addGap(); rc.addGap(); assertEquals(rc.getModalCount(), 2); } @Test(groups = "Functional") public void testGetResiduesForCount() { ResidueCount rc = new ResidueCount(); rc.add('c'); rc.add('g'); rc.add('c'); assertEquals(rc.getResiduesForCount(2), "C"); assertEquals(rc.getResiduesForCount(1), "G"); assertEquals(rc.getResiduesForCount(3), ""); assertEquals(rc.getResiduesForCount(0), ""); assertEquals(rc.getResiduesForCount(-1), ""); // modal count is in the 'short overflow' counts rc = new ResidueCount(); rc.add('c'); rc.put('g', Short.MAX_VALUE); rc.add('G'); assertEquals(rc.getResiduesForCount(Short.MAX_VALUE + 1), "G"); assertEquals(rc.getResiduesForCount(1), "C"); // modal count is in the 'other data' counts rc = new ResidueCount(); rc.add('Q'); rc.add('{'); rc.add('{'); assertEquals(rc.getResiduesForCount(1), "Q"); assertEquals(rc.getResiduesForCount(2), "{"); // residues share modal count rc = new ResidueCount(); rc.add('G'); rc.add('G'); rc.add('c'); rc.add('C'); rc.add('U'); assertEquals(rc.getResiduesForCount(1), "U"); assertEquals(rc.getResiduesForCount(2), "CG"); // expected and unexpected symbols share modal count rc = new ResidueCount(); rc.add('G'); rc.add('t'); rc.add('['); rc.add('['); rc.add('t'); rc.add('G'); rc.add('c'); rc.add('C'); rc.add('U'); assertEquals(rc.getResiduesForCount(1), "U"); assertEquals(rc.getResiduesForCount(2), "CGT["); } @Test(groups = "Functional") public void testGetSymbolCounts() { ResidueCount rc = new ResidueCount(); rc.add('q'); rc.add('c'); rc.add('Q'); rc.add('J'); // 'otherData' rc.add('q'); rc.add('x'); SymbolCounts sc = rc.getSymbolCounts(); Assert.assertArrayEquals(new char[] { 'C', 'Q', 'X', 'J' }, sc.symbols); Assert.assertArrayEquals(new int[] { 1, 3, 1, 1 }, sc.values); // now with overflow to int counts rc.put('g', Short.MAX_VALUE); rc.add('g'); sc = rc.getSymbolCounts(); Assert.assertArrayEquals(new char[] { 'C', 'G', 'Q', 'X', 'J' }, sc.symbols); Assert.assertArrayEquals(new int[] { 1, 32768, 3, 1, 1 }, sc.values); } @Test(groups = "Functional") public void testToString() { ResidueCount rc = new ResidueCount(); rc.add('q'); rc.add('c'); rc.add('Q'); assertEquals(rc.toString(), "[ C:1 Q:2 ]"); // add 'other data' rc.add('{'); assertEquals(rc.toString(), "[ C:1 Q:2 {:1 ]"); // switch from short to int counting: rc.put('G', Short.MAX_VALUE); rc.add('g'); assertEquals(rc.toString(), "[ C:1 G:32768 Q:2 {:1 ]"); } }