JAL-1759 merge from develop
[jalview.git] / test / jalview / analysis / AlignmentUtilsTests.java
index 9ef1b9a..61b2487 100644 (file)
  */
 package jalview.analysis;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
 
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.junit.Test;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.assertSame;
+import static org.testng.AssertJUnit.assertTrue;
 
 import jalview.datamodel.AlignedCodonFrame;
 import jalview.datamodel.Alignment;
@@ -54,7 +43,20 @@ import jalview.io.FormatAdapter;
 import jalview.util.MapList;
 import jalview.util.MappingUtils;
 
-public class AlignmentUtilsTests 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.testng.annotations.Test;
+
+public class AlignmentUtilsTests
 {
   // @formatter:off
   private static final String TEST_DATA = 
@@ -89,13 +91,16 @@ public class AlignmentUtilsTests
           "GGGTCAGGCAGT\n";
   // @formatter:on
 
-  public static Sequence ts=new Sequence("short","ASDASDASDASDASDASDASDASDASDASDASDASDASD");
+  // public static Sequence ts=new
+  // Sequence("short","ASDASDASDASDASDASDASDASDASDASDASDASDASD");
+  public static Sequence ts = new Sequence("short",
+          "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm");
 
-  @Test
-  public void testExpandFlanks()
+  @Test(groups ={ "Functional" })
+  public void testExpandContext()
   {
     AlignmentI al = new Alignment(new Sequence[] {});
-    for (int i=4;i<14;i+=3)
+    for (int i = 4; i < 14; i += 2)
     {
       SequenceI s1=ts.deriveSequence().getSubSequence(i, i+7);
       al.addSequence(s1);
@@ -103,25 +108,139 @@ public class AlignmentUtilsTests
     System.out.println(new AppletFormatAdapter().formatSequences("Clustal", al, true));
     for (int flnk=-1;flnk<25; flnk++)
     {
-      AlignmentI exp;
-      System.out.println("\nFlank size: "+flnk);
-      System.out.println(new AppletFormatAdapter().formatSequences("Clustal", exp=AlignmentUtils.expandContext(al, flnk), true));
-      if (flnk==-1) {
-        for (SequenceI sq:exp.getSequences())
+      AlignmentI exp = AlignmentUtils.expandContext(al, flnk);
+      System.out.println("\nFlank size: " + flnk);
+      System.out.println(new AppletFormatAdapter().formatSequences(
+              "Clustal", exp, true));
+      if (flnk == -1)
       {
+        /*
+         * Full expansion to complete sequences
+         */
+        for (SequenceI sq : exp.getSequences())
+        {
           String ung = sq.getSequenceAsString().replaceAll("-+", "");
-          assertTrue("Flanking sequence not the same as original dataset sequence.\n"+ung+"\n"+sq.getDatasetSequence().getSequenceAsString(),ung.equalsIgnoreCase(sq.getDatasetSequence().getSequenceAsString()));
+          final String errorMsg = "Flanking sequence not the same as original dataset sequence.\n"
+                  + ung
+                  + "\n"
+                  + sq.getDatasetSequence().getSequenceAsString();
+          assertTrue(errorMsg, ung.equalsIgnoreCase(sq.getDatasetSequence()
+                  .getSequenceAsString()));
+        }
       }
+      else if (flnk == 24)
+      {
+        /*
+         * Last sequence is fully expanded, others have leading gaps to match
+         */
+        assertTrue(exp.getSequenceAt(4).getSequenceAsString()
+                .startsWith("abc"));
+        assertTrue(exp.getSequenceAt(3).getSequenceAsString()
+                .startsWith("--abc"));
+        assertTrue(exp.getSequenceAt(2).getSequenceAsString()
+                .startsWith("----abc"));
+        assertTrue(exp.getSequenceAt(1).getSequenceAsString()
+                .startsWith("------abc"));
+        assertTrue(exp.getSequenceAt(0).getSequenceAsString()
+                .startsWith("--------abc"));
       }
     }
-    }    
+  }
+
+  /**
+   * Test that annotations are correctly adjusted by expandContext
+   */
+  @Test(groups ={ "Functional" })
+  public void testExpandContext_annotation()
+  {
+    AlignmentI al = new Alignment(new Sequence[]
+    {});
+    SequenceI ds = new Sequence("Seq1", "ABCDEFGHI");
+    // subsequence DEF:
+    SequenceI seq1 = ds.deriveSequence().getSubSequence(3, 6);
+    al.addSequence(seq1);
+
+    /*
+     * Annotate DEF with 4/5/6 respectively
+     */
+    Annotation[] anns = new Annotation[]
+    { new Annotation(4), new Annotation(5), new Annotation(6) };
+    AlignmentAnnotation ann = new AlignmentAnnotation("SS",
+            "secondary structure", anns);
+    seq1.addAlignmentAnnotation(ann);
+
+    /*
+     * The annotations array should match aligned positions
+     */
+    assertEquals(3, ann.annotations.length);
+    assertEquals(4, ann.annotations[0].value, 0.001);
+    assertEquals(5, ann.annotations[1].value, 0.001);
+    assertEquals(6, ann.annotations[2].value, 0.001);
+
+    /*
+     * Check annotation to sequence position mappings before expanding the
+     * sequence; these are set up in Sequence.addAlignmentAnnotation ->
+     * Annotation.setSequenceRef -> createSequenceMappings
+     */
+    assertNull(ann.getAnnotationForPosition(1));
+    assertNull(ann.getAnnotationForPosition(2));
+    assertNull(ann.getAnnotationForPosition(3));
+    assertEquals(4, ann.getAnnotationForPosition(4).value, 0.001);
+    assertEquals(5, ann.getAnnotationForPosition(5).value, 0.001);
+    assertEquals(6, ann.getAnnotationForPosition(6).value, 0.001);
+    assertNull(ann.getAnnotationForPosition(7));
+    assertNull(ann.getAnnotationForPosition(8));
+    assertNull(ann.getAnnotationForPosition(9));
+
+    /*
+     * Expand the subsequence to the full sequence abcDEFghi
+     */
+    AlignmentI expanded = AlignmentUtils.expandContext(al, -1);
+    assertEquals("abcDEFghi", expanded.getSequenceAt(0)
+            .getSequenceAsString());
+
+    /*
+     * Confirm the alignment and sequence have the same SS annotation,
+     * referencing the expanded sequence
+     */
+    ann = expanded.getSequenceAt(0).getAnnotation()[0];
+    assertSame(ann, expanded.getAlignmentAnnotation()[0]);
+    assertSame(expanded.getSequenceAt(0), ann.sequenceRef);
+
+    /*
+     * The annotations array should have null values except for annotated
+     * positions
+     */
+    assertNull(ann.annotations[0]);
+    assertNull(ann.annotations[1]);
+    assertNull(ann.annotations[2]);
+    assertEquals(4, ann.annotations[3].value, 0.001);
+    assertEquals(5, ann.annotations[4].value, 0.001);
+    assertEquals(6, ann.annotations[5].value, 0.001);
+    assertNull(ann.annotations[6]);
+    assertNull(ann.annotations[7]);
+    assertNull(ann.annotations[8]);
+
+    /*
+     * sequence position mappings should be unchanged
+     */
+    assertNull(ann.getAnnotationForPosition(1));
+    assertNull(ann.getAnnotationForPosition(2));
+    assertNull(ann.getAnnotationForPosition(3));
+    assertEquals(4, ann.getAnnotationForPosition(4).value, 0.001);
+    assertEquals(5, ann.getAnnotationForPosition(5).value, 0.001);
+    assertEquals(6, ann.getAnnotationForPosition(6).value, 0.001);
+    assertNull(ann.getAnnotationForPosition(7));
+    assertNull(ann.getAnnotationForPosition(8));
+    assertNull(ann.getAnnotationForPosition(9));
+  }
 
   /**
    * Test method that returns a map of lists of sequences by sequence name.
    * 
    * @throws IOException
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testGetSequencesByName() throws IOException
   {
     final String data = ">Seq1Name\nKQYL\n" + ">Seq2Name\nRFPW\n"
@@ -146,7 +265,7 @@ public class AlignmentUtilsTests
    */
   protected AlignmentI loadAlignment(final String data, String format) throws IOException
   {
-    Alignment a = new FormatAdapter().readFile(data,
+    AlignmentI a = new FormatAdapter().readFile(data,
             AppletFormatAdapter.PASTE, format);
     a.setDataset(null);
     return a;
@@ -159,7 +278,7 @@ public class AlignmentUtilsTests
    * 
    * @throws IOException
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMapProteinToCdna_noXrefs() throws IOException
   {
     List<SequenceI> protseqs = new ArrayList<SequenceI>();
@@ -222,7 +341,7 @@ public class AlignmentUtilsTests
   /**
    * Test for the alignSequenceAs method that takes two sequences and a mapping.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testAlignSequenceAs_withMapping_noIntrons()
   {
     MapList map = new MapList(new int[]
@@ -268,7 +387,7 @@ public class AlignmentUtilsTests
   /**
    * Test for the alignSequenceAs method that takes two sequences and a mapping.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testAlignSequenceAs_withMapping_withIntrons()
   {
     /*
@@ -318,7 +437,7 @@ public class AlignmentUtilsTests
   /**
    * Test for the case where not all of the protein sequence is mapped to cDNA.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testAlignSequenceAs_withMapping_withUnmappedProtein()
   {
     
@@ -368,7 +487,7 @@ public class AlignmentUtilsTests
   /**
    * Test for the alignSequenceAs method where we preserve gaps in introns only.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testAlignSequenceAs_keepIntronGapsOnly()
   {
 
@@ -387,7 +506,7 @@ public class AlignmentUtilsTests
    * Test for the method that generates an aligned translated sequence from one
    * mapping.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testGetAlignedTranslation_dnaLikeProtein()
   {
     // dna alignment will be replaced
@@ -411,7 +530,7 @@ public class AlignmentUtilsTests
   /**
    * Test the method that realigns protein to match mapped codon alignment.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testAlignProteinAsDna()
   {
     // seq1 codons are [1,2,3] [4,5,6] [7,8,9] [10,11,12]
@@ -455,7 +574,7 @@ public class AlignmentUtilsTests
    * Test the method that tests whether a CDNA sequence translates to a protein
    * sequence
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testTranslatesAs()
   {
     assertTrue(AlignmentUtils.translatesAs("tttcccaaaggg".toCharArray(), 0,
@@ -494,7 +613,7 @@ public class AlignmentUtilsTests
    * 
    * @throws IOException
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMapProteinToCdna_withStartAndStopCodons()
           throws IOException
   {
@@ -587,7 +706,7 @@ public class AlignmentUtilsTests
    * 
    * @throws IOException
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMapProteinToCdna_withXrefs() throws IOException
   {
     List<SequenceI> protseqs = new ArrayList<SequenceI>();
@@ -663,7 +782,7 @@ public class AlignmentUtilsTests
    * 
    * @throws IOException
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMapProteinToCdna_prioritiseXrefs() throws IOException
   {
     List<SequenceI> protseqs = new ArrayList<SequenceI>();
@@ -713,7 +832,7 @@ public class AlignmentUtilsTests
    * Test the method that shows or hides sequence annotations by type(s) and
    * selection group.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testShowOrHideSequenceAnnotations()
   {
     SequenceI seq1 = new Sequence("Seq1", "AAA");
@@ -821,7 +940,7 @@ public class AlignmentUtilsTests
   /**
    * Tests for the method that checks if one sequence cross-references another
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testHasCrossRef()
   {
     assertFalse(AlignmentUtils.hasCrossRef(null, null));
@@ -850,7 +969,7 @@ public class AlignmentUtilsTests
    * Tests for the method that checks if either sequence cross-references the
    * other
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testHaveCrossRef()
   {
     assertFalse(AlignmentUtils.hasCrossRef(null, null));
@@ -880,7 +999,7 @@ public class AlignmentUtilsTests
   /**
    * Test the method that extracts the exon-only part of a dna alignment.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMakeExonAlignment()
   {
     SequenceI dna1 = new Sequence("dna1", "aaaGGGcccTTTaaa");
@@ -975,7 +1094,7 @@ public class AlignmentUtilsTests
    * already has a protein product (Uniprot translation) which in turn has an
    * x-ref to the EMBLCDS record.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMakeExonSequences()
   {
     SequenceI dna1 = new Sequence("dna1", "aaaGGGcccTTTaaa");
@@ -1017,7 +1136,7 @@ public class AlignmentUtilsTests
    * its product mappings, for the case where there are multiple exon mappings
    * to different protein products.
    */
-  @Test
+  @Test(groups ={ "Functional" })
   public void testMakeExonAlignment_multipleProteins()
   {
     SequenceI dna1 = new Sequence("dna1", "aaaGGGcccTTTaaa");