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.Assert;
+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" })
@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);
}
/**
* @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();
// 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"
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);
{
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
}
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];
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++)
{
{
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);
}
}
}
}
}
- /*
- * 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)
{
- 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;
+ 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
+ {
+ // 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
}
else
{
- System.err.println("Annotation Element Mismatch\nElement "
+ fail("Annotation Element Mismatch\nElement "
+ i
+ " in original: "
+ (annot_or.annotations[i] == null ? "is null"
+ " 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";
+
+ String annFileFullWuss = "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
+ {
+ roundTripSSForRNA(aliFile, annFile);
+ }
+
+ @Test(groups = { "Functional" })
+ public void fullWUSSsecondaryStructureForRNASequence() throws Exception
+ {
+ roundTripSSForRNA(aliFile, annFileFullWuss);
+ }
+
+ private static void roundTripSSForRNA(String aliFile, String annFile)
+ 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);
+
}
}