JAL-1619 refactored cDNA translation; modified codon comparison; tests
[jalview.git] / test / jalview / analysis / DnaTest.java
index 49a544d..43ee5f2 100644 (file)
@@ -4,13 +4,13 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import jalview.api.AlignViewportI;
+import jalview.datamodel.AlignedCodon;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.ColumnSelection;
 import jalview.gui.AlignViewport;
 import jalview.io.FormatAdapter;
 
 import java.io.IOException;
-import java.util.Arrays;
 
 import org.junit.Test;
 
@@ -171,7 +171,7 @@ public class DnaTest
    * @throws IOException
    */
   @Test
-  public void testTranslatCdna_hiddenColumns() throws IOException
+  public void testTranslateCdna_hiddenColumns() throws IOException
   {
     AlignmentI alf = new FormatAdapter().readFile(fasta,
             FormatAdapter.PASTE, "FASTA");
@@ -188,6 +188,15 @@ public class DnaTest
   }
 
   /**
+   * Use this test to help debug into any cases of interest.
+   */
+  @Test
+  public void testCompareCodonPos_oneOnly()
+  {
+    assertFollows("-AA--A", "G--GG"); // 2 shifted seq2, 3 shifted seq1
+  }
+
+  /**
    * Tests for method that compares 'alignment' of two codon position triplets.
    */
   @Test
@@ -196,10 +205,8 @@ public class DnaTest
     /*
      * Returns 0 for any null argument
      */
-    assertEquals(0, Dna.compareCodonPos(new int[]
-      { 1, 2, 3 }, null));
-    assertEquals(0, Dna.compareCodonPos(null, new int[]
-      { 1, 2, 3 }));
+    assertEquals(0, Dna.compareCodonPos(new AlignedCodon(1, 2, 3), null));
+    assertEquals(0, Dna.compareCodonPos(null, new AlignedCodon(1, 2, 3)));
 
     /*
      * Work through 27 combinations. First 9 cases where first position matches.
@@ -209,10 +216,9 @@ public class DnaTest
     assertPrecedes("AAA", "GG-G"); // 2 matches, 3 shifted seq2
     assertFollows("A-AA", "GG-G"); // 2 shifted seq1, 3 matches
     assertFollows("A-A-A", "GG-G"); // 2 shifted seq1, 3 shifted seq1
-    // TODO is this right?
     assertPrecedes("A-AA", "GG--G"); // 2 shifted seq1, 3 shifted seq2
     assertPrecedes("AA-A", "G-GG"); // 2 shifted seq2, 3 matches
-    assertPrecedes("AA--A", "G-GG"); // 2 shifted seq2, 3 shifted seq1
+    assertFollows("AA--A", "G-GG"); // 2 shifted seq2, 3 shifted seq1
     assertPrecedes("AAA", "G-GG"); // 2 shifted seq2, 3 shifted seq2
 
     /*
@@ -220,13 +226,14 @@ public class DnaTest
      */
     assertFollows("-AAA", "G-GG"); // 2 and 3 match
     assertFollows("-AA-A", "G-GG"); // 2 matches, 3 shifted seq1
-    assertPrecedes("-AAA", "G-G-G"); // 2 matches, 3 shifted seq2
+    // 'enclosing' case: pick first to start precedes
+    assertFollows("-AAA", "G-G-G"); // 2 matches, 3 shifted seq2
     assertFollows("-A-AA", "G-G-G"); // 2 shifted seq1, 3 matches
     assertFollows("-A-A-A", "G-G-G"); // 2 shifted seq1, 3 shifted seq1
-    // is this right? codon2 ends after codon1
-    assertPrecedes("-A-AA", "G-G--G"); // 2 shifted seq1, 3 shifted seq2
-    assertPrecedes("-AA-A", "G--GG"); // 2 shifted seq2, 3 matches
-    assertPrecedes("-AA--A", "G--GG"); // 2 shifted seq2, 3 shifted seq1
+    // 'enclosing' case: pick first to start precedes
+    assertFollows("-A-AA", "G-G--G"); // 2 shifted seq1, 3 shifted seq2
+    assertFollows("-AA-A", "G--GG"); // 2 shifted seq2, 3 matches
+    assertFollows("-AA--A", "G--GG"); // 2 shifted seq2, 3 shifted seq1
     assertPrecedes("-AAA", "G--GG"); // 2 shifted seq2, 3 shifted seq2
 
     /*
@@ -236,31 +243,71 @@ public class DnaTest
     assertPrecedes("A-A-A", "-GGG"); // 2 matches, 3 shifted seq1
     assertPrecedes("A-AA", "-GG-G"); // 2 matches, 3 shifted seq2
     assertPrecedes("A--AA", "-GG-G"); // 2 shifted seq1, 3 matches
-    assertPrecedes("A--AA", "-GGG"); // 2 shifted seq1, 3 shifted seq1
+    // 'enclosing' case with middle base deciding:
+    assertFollows("A--AA", "-GGG"); // 2 shifted seq1, 3 shifted seq1
     assertPrecedes("A--AA", "-GG--G"); // 2 shifted seq1, 3 shifted seq2
     assertPrecedes("AA-A", "-GGG"); // 2 shifted seq2, 3 matches
     assertPrecedes("AA--A", "-GGG"); // 2 shifted seq2, 3 shifted seq1
     assertPrecedes("AAA", "-GGG"); // 2 shifted seq2, 3 shifted seq2
+  }
 
-    /*
-     * two codon positions can each 'precede' the other! the comparison is
-     * biased to the first sequence
-     */
-    // TODO is this correct?
-    assertPrecedes("-A--AA", "--GGG");
-    assertPrecedes("--AAA", "-A--AA");
+  /**
+   * Test that all the cases in testCompareCodonPos have a 'symmetric'
+   * comparison (without checking the actual comparison result).
+   */
+  @Test
+  public void testCompareCodonPos_isSymmetric()
+  {
+    assertSymmetric("AAA", "GGG");
+    assertSymmetric("AA-A", "GGG");
+    assertSymmetric("AAA", "GG-G");
+    assertSymmetric("A-AA", "GG-G");
+    assertSymmetric("A-A-A", "GG-G");
+    assertSymmetric("A-AA", "GG--G");
+    assertSymmetric("AA-A", "G-GG");
+    assertSymmetric("AA--A", "G-GG");
+    assertSymmetric("AAA", "G-GG");
+    assertSymmetric("-AAA", "G-GG");
+    assertSymmetric("-AA-A", "G-GG");
+    assertSymmetric("-AAA", "G-G-G");
+    assertSymmetric("-A-AA", "G-G-G");
+    assertSymmetric("-A-A-A", "G-G-G");
+    assertSymmetric("-A-AA", "G-G--G");
+    assertSymmetric("-AA-A", "G--GG");
+    assertSymmetric("-AA--A", "G--GG");
+    assertSymmetric("-AAA", "G--GG");
+    assertSymmetric("A-AA", "-GGG");
+    assertSymmetric("A-A-A", "-GGG");
+    assertSymmetric("A-AA", "-GG-G");
+    assertSymmetric("A--AA", "-GG-G");
+    assertSymmetric("A--AA", "-GGG");
+    assertSymmetric("A--AA", "-GG--G");
+    assertSymmetric("AA-A", "-GGG");
+    assertSymmetric("AA--A", "-GGG");
+    assertSymmetric("AAA", "-GGG");
+  }
+
+  private void assertSymmetric(String codon1, String codon2)
+  {
+    assertEquals("Comparison of '" + codon1 + "' and '" + codon2
+            + " not symmetric", Integer.signum(compare(codon1, codon2)),
+            -Integer.signum(compare(codon2, codon1)));
   }
 
   /**
    * Assert that the first sequence should map to the same position as the
-   * second in a translated alignment
+   * second in a translated alignment. Also checks that this is true if the
+   * order of the codons is reversed.
    * 
    * @param codon1
    * @param codon2
    */
   private void assertMatches(String codon1, String codon2)
   {
-    assertEquals("Expected match (0)", 0, compare(codon1, codon2));
+    assertEquals("Expected '" + codon1 + "' matches '" + codon2 + "'", 0,
+            compare(codon1, codon2));
+    assertEquals("Expected '" + codon2 + "' matches '" + codon1 + "'", 0,
+            compare(codon2, codon1));
   }
 
   /**
@@ -272,7 +319,8 @@ public class DnaTest
    */
   private void assertPrecedes(String codon1, String codon2)
   {
-    assertEquals("Expected precedes (-1)", -1, compare(codon1, codon2));
+    assertEquals("Expected '" + codon1 + "'  precedes '" + codon2 + "'",
+            -1, compare(codon1, codon2));
   }
 
   /**
@@ -284,7 +332,8 @@ public class DnaTest
    */
   private void assertFollows(String codon1, String codon2)
   {
-    assertEquals("Expected follows (1)", 1, compare(codon1, codon2));
+    assertEquals("Expected '" + codon1 + "'  follows '" + codon2 + "'", 1,
+            compare(codon1, codon2));
   }
 
   /**
@@ -297,10 +346,10 @@ public class DnaTest
    */
   private int compare(String s1, String s2)
   {
-    final int[] cd1 = convertCodon(s1);
-    final int[] cd2 = convertCodon(s2);
-    System.out.println("K: " + s1 + "  " + Arrays.toString(cd1));
-    System.out.println("G: " + s2 + "  " + Arrays.toString(cd2));
+    final AlignedCodon cd1 = convertCodon(s1);
+    final AlignedCodon cd2 = convertCodon(s2);
+    System.out.println("K: " + s1 + "  " + cd1.toString());
+    System.out.println("G: " + s2 + "  " + cd2.toString());
     System.out.println();
     return Dna.compareCodonPos(cd1, cd2);
   }
@@ -312,18 +361,18 @@ public class DnaTest
    * @param s
    * @return
    */
-  private int[] convertCodon(String s)
+  private AlignedCodon convertCodon(String s)
   {
-    int[] result = new int[3];
+    int[] codon = new int[3];
     int i = 0;
     for (int j = 0; j < s.length(); j++)
     {
       if (s.charAt(j) != '-')
       {
-        result[i++] = j;
+        codon[i++] = j;
       }
     }
-    return result;
+    return new AlignedCodon(codon[0], codon[1], codon[2]);
   }
 
   /**
@@ -332,8 +381,8 @@ public class DnaTest
   @Test
   public void testConvertCodon()
   {
-    assertEquals("[0, 1, 2]", Arrays.toString(convertCodon("AAA")));
-    assertEquals("[0, 2, 5]", Arrays.toString(convertCodon("A-A--A")));
-    assertEquals("[1, 3, 4]", Arrays.toString(convertCodon("-A-AA-")));
+    assertEquals("[0, 1, 2]", convertCodon("AAA").toString());
+    assertEquals("[0, 2, 5]", convertCodon("A-A--A").toString());
+    assertEquals("[1, 3, 4]", convertCodon("-A-AA-").toString());
   }
 }