JAL-2507 simplify round trip test via AppletFormatAdapter
[jalview.git] / test / jalview / io / StockholmFileTest.java
index bdd311b..185eedf 100644 (file)
@@ -30,24 +30,34 @@ import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.gui.JvOptionPane;
 
 import java.io.File;
 import java.util.BitSet;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 public class StockholmFileTest
 {
 
+  @BeforeClass(alwaysRun = true)
+  public void setUpJvOptionPane()
+  {
+    JvOptionPane.setInteractiveMode(false);
+    JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
+  }
+
   static String PfamFile = "examples/PF00111_seed.stk",
           RfamFile = "examples/RF00031_folded.stk";
 
   @Test(groups = { "Functional" })
   public void pfamFileIO() throws Exception
   {
-    testFileIOwithFormat(new File(PfamFile), FileFormat.Stockholm, -1, 0);
+    testFileIOwithFormat(new File(PfamFile), FileFormat.Stockholm, -1, 0,
+            false);
   }
 
   @Test(groups = { "Functional" })
@@ -72,7 +82,8 @@ public class StockholmFileTest
   @Test(groups = { "Functional" })
   public void rfamFileIO() throws Exception
   {
-    testFileIOwithFormat(new File(RfamFile), FileFormat.Stockholm, 2, 1);
+    testFileIOwithFormat(new File(RfamFile), FileFormat.Stockholm, 2, 1,
+            false);
   }
 
   /**
@@ -84,10 +95,11 @@ public class StockholmFileTest
    * @param ioformat
    *          - label for IO class used to write and read back in the data from
    *          f
+   * @param ignoreRowVisibility
    */
 
   public static void testFileIOwithFormat(File f, FileFormatI ioformat,
-          int naliannot, int nminseqann)
+          int naliannot, int nminseqann, boolean ignoreRowVisibility)
   {
     System.out.println("Reading file: " + f);
     String ff = f.getPath();
@@ -103,7 +115,7 @@ public class StockholmFileTest
       // make sure dataset is initialised ? not sure about this
       for (int i = 0; i < al.getSequencesArray().length; ++i)
       {
-        al.getSequenceAt(i).setDatasetSequence(al.getSequenceAt(i));
+        al.getSequenceAt(i).createDatasetSequence();
       }
       String outputfile = rf.formatSequences(ioformat, al, true);
       System.out.println("Output file in '" + ioformat + "':\n"
@@ -165,6 +177,27 @@ public class StockholmFileTest
   public static void testAlignmentEquivalence(AlignmentI al,
           AlignmentI al_input, boolean ignoreFeatures)
   {
+  }
+
+  /**
+   * assert alignment equivalence
+   * 
+   * @param al
+   *          'original'
+   * @param al_input
+   *          'secondary' or generated alignment from some datapreserving
+   *          transformation
+   * @param ignoreFeatures
+   *          when true, differences in sequence feature annotation are ignored
+   * 
+   * @param ignoreRowVisibility
+   *          when true, do not fail if there are differences in the visibility
+   *          of annotation rows
+   */
+  public static void testAlignmentEquivalence(AlignmentI al,
+          AlignmentI al_input, boolean ignoreFeatures,
+          boolean ignoreRowVisibility)
+  {
     assertNotNull("Original alignment was null", al);
     assertNotNull("Generated alignment was null", al_input);
 
@@ -192,13 +225,18 @@ public class StockholmFileTest
       {
         if (aa_new.length > i)
         {
-          assertTrue("Different alignment annotation at position " + i,
-                  equalss(aa_original[i], aa_new[i]));
+          assertEqualSecondaryStructure(
+                  "Different alignment annotation at position " + i,
+                  aa_original[i], aa_new[i]);
           // compare graphGroup or graph properties - needed to verify JAL-1299
           assertEquals("Graph type not identical.", aa_original[i].graph,
                   aa_new[i].graph);
-          assertEquals("Visibility not identical.", aa_original[i].visible,
+          if (!ignoreRowVisibility)
+          {
+            assertEquals("Visibility not identical.",
+                    aa_original[i].visible,
                   aa_new[i].visible);
+          }
           assertEquals("Threshold line not identical.",
                   aa_original[i].threshold, aa_new[i].threshold);
           // graphGroup may differ, but pattern should be the same
@@ -228,7 +266,7 @@ public class StockholmFileTest
     }
     assertEquals(
             "Generated and imported alignment have different annotation sets",
-            aa_new_size, aa_original_size);
+            aa_original_size, aa_new_size);
 
     // check sequences, annotation and features
     SequenceI[] seq_original = new SequenceI[al.getSequencesArray().length];
@@ -281,8 +319,7 @@ public class StockholmFileTest
 
             assertEquals("different number of features",
                     seq_original[i].getSequenceFeatures().length,
-                    seq_new[in]
-                    .getSequenceFeatures().length);
+                    seq_new[in].getSequenceFeatures().length);
 
             for (int feat = 0; feat < seq_original[i].getSequenceFeatures().length; feat++)
             {
@@ -302,8 +339,9 @@ public class StockholmFileTest
               {
                 annot_original = al.getSequenceAt(i).getAnnotation()[j];
                 annot_new = al_input.getSequenceAt(in).getAnnotation()[j];
-                assertTrue("Different annotation elements",
-                        equalss(annot_original, annot_new));
+                assertEqualSecondaryStructure(
+                        "Different annotation elements", annot_original,
+                        annot_new);
               }
             }
           }
@@ -325,39 +363,57 @@ public class StockholmFileTest
     }
   }
 
-  /*
-   * compare annotations
-   */
-  private static boolean equalss(AlignmentAnnotation annot_or,
+  private static void assertEqualSecondaryStructure(String message,
+          AlignmentAnnotation annot_or,
           AlignmentAnnotation annot_new)
   {
+    // TODO: test to cover this assert behaves correctly for all allowed
+    // variations of secondary structure annotation row equivalence
     if (annot_or.annotations.length != annot_new.annotations.length)
     {
-      System.err.println("Different lengths for annotation row elements: "
+      fail("Different lengths for annotation row elements: "
               + annot_or.annotations.length + "!="
               + annot_new.annotations.length);
-      return false;
     }
+    boolean isRna = annot_or.isRNA();
+    assertTrue("Expected " + (isRna ? " valid RNA " : " no RNA ")
+            + " secondary structure in the row.",
+            isRna == annot_new.isRNA());
     for (int i = 0; i < annot_or.annotations.length; i++)
     {
       Annotation an_or = annot_or.annotations[i], an_new = annot_new.annotations[i];
       if (an_or != null && an_new != null)
       {
-        if (!an_or.displayCharacter.trim().equals(
-                an_new.displayCharacter.trim())
-                || !("" + an_or.secondaryStructure).trim().equals(
-                        ("" + an_new.secondaryStructure).trim())
-                || (an_or.description != an_new.description && !((an_or.description == null && an_new.description
-                        .trim().length() == 0)
-                        || (an_new.description == null && an_or.description
-                                .trim().length() == 0) || an_or.description
-                        .trim().equals(an_new.description.trim()))))
+
+        if (isRna)
+        {
+          if (an_or.secondaryStructure != an_new.secondaryStructure
+                  || an_or.value != an_new.value)
+          {
+            fail("Different RNA secondary structure at column " + i
+                    + " expected: [" + annot_or.annotations[i].toString()
+                    + "] but got: [" + annot_new.annotations[i].toString()
+                    + "]");
+          }
+        }
+        else
         {
-          System.err.println("Annotation Element Mismatch\nElement " + i
-                  + " in original: " + annot_or.annotations[i].toString()
-                  + "\nElement " + i + " in new: "
-                  + annot_new.annotations[i].toString());
-          return false;
+          // not RNA secondary structure, so expect all elements to match...
+          if (!an_or.displayCharacter.trim().equals(
+                  an_new.displayCharacter.trim())
+                  || !("" + an_or.secondaryStructure).trim().equals(
+                          ("" + an_new.secondaryStructure).trim())
+                  || (an_or.description != an_new.description && !((an_or.description == null && an_new.description
+                          .trim().length() == 0)
+                          || (an_new.description == null && an_or.description
+                                  .trim().length() == 0) || an_or.description
+                          .trim().equals(an_new.description.trim()))))
+          {
+            fail("Annotation Element Mismatch\nElement " + i
+                    + " in original: " + annot_or.annotations[i].toString()
+                    + "\nElement " + i + " in new: "
+                    + annot_new.annotations[i].toString());
+          }
         }
       }
       else if (annot_or.annotations[i] == null
@@ -367,7 +423,7 @@ public class StockholmFileTest
       }
       else
       {
-        System.err.println("Annotation Element Mismatch\nElement "
+        fail("Annotation Element Mismatch\nElement "
                 + i
                 + " in original: "
                 + (annot_or.annotations[i] == null ? "is null"
@@ -377,9 +433,36 @@ public class StockholmFileTest
                 + " in new: "
                 + (annot_new.annotations[i] == null ? "is null"
                         : annot_new.annotations[i].toString()));
-        return false;
       }
     }
-    return true;
+  }
+
+  String aliFile = ">Dm\nAAACCCUUUUACACACGGGAAAGGG";
+  String annFile = "JALVIEW_ANNOTATION\n# Created: Thu May 04 11:16:52 BST 2017\n\n"
+          + "SEQUENCE_REF\tDm\nNO_GRAPH\tsecondary structure\tsecondary structure\t"
+          + "(|(|(|(|, .|, .|, .|, .|)|)|)|)|\t0.0\nROWPROPERTIES\t"
+          + "secondary structure\tscaletofit=true\tshowalllabs=true\tcentrelabs=false";
+
+  @Test(groups = { "Functional" })
+  public void secondaryStructureForRNASequence() throws Exception
+  {
+    AlignmentI al = new AppletFormatAdapter().readFile(aliFile,
+            DataSourceType.PASTE, jalview.io.FileFormat.Fasta);
+    AnnotationFile aaf = new AnnotationFile();
+    aaf.readAnnotationFile(al, annFile, DataSourceType.PASTE);
+    al.getAlignmentAnnotation()[0].visible = true;
+
+    // TODO: create a better 'save as <format>' pattern
+    StockholmFile sf = new StockholmFile(al);
+
+    String stockholmFile = sf.print(al.getSequencesArray(), true);
+
+    AlignmentI newAl = new AppletFormatAdapter().readFile(stockholmFile,
+            DataSourceType.PASTE, jalview.io.FileFormat.Stockholm);
+    // AlignmentUtils.showOrHideSequenceAnnotations(newAl.getViewport()
+    // .getAlignment(), Arrays.asList("Secondary Structure"), newAl
+    // .getViewport().getAlignment().getSequences(), true, true);
+    testAlignmentEquivalence(al, newAl, true, true);
+
   }
 }