JAL-1499 refactored processGeneOrDomain, expanded test
[jalview.git] / test / jalview / io / MegaFileTest.java
1 package jalview.io;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertFalse;
5 import static org.testng.AssertJUnit.assertNull;
6 import static org.testng.AssertJUnit.assertTrue;
7 import static org.testng.AssertJUnit.fail;
8
9 import jalview.datamodel.AlignmentI;
10 import jalview.datamodel.Sequence;
11 import jalview.datamodel.SequenceFeature;
12 import jalview.datamodel.SequenceI;
13
14 import java.io.IOException;
15 import java.util.Vector;
16
17 import org.testng.annotations.Test;
18
19 /*
20  * Unit tests for MegaFile - read and write in MEGA format(s).
21  */
22 public class MegaFileTest
23 {
24   private static final String TWENTY_CHARS = "9876543210abcdefghij";
25
26   private static final String THIRTY_CHARS = "0123456789klmnopqrstABCDEFGHIJ";
27
28   //@formatter:off
29   private static final String INTERLEAVED = 
30           "#MEGA\n"+ 
31           "TITLE: Interleaved sequence data\n\n" + 
32           "#U455   ABCDEF\n" + 
33           "#CPZANT  MNOPQR\n\n" + 
34           "#U455   KLMNOP\n" + 
35           "#CPZANT WXYZGC";
36
37   private static final String INTERLEAVED_NOHEADERS = 
38           "#U455   ABCDEF\n" 
39           + "#CPZANT MNOPQR\n\n" 
40           + "#U455   KLMNOP\n"
41           + "#CPZANT WXYZGC\n";
42
43   // interleaved sequences, with 50 residues
44   private static final String INTERLEAVED_50RESIDUES = 
45           "#MEGA\n"
46           + "!TITLE Interleaved sequence data\n\n"
47           + "#U455 " + THIRTY_CHARS + TWENTY_CHARS + "\n" 
48           + "#CPZANT " + TWENTY_CHARS + THIRTY_CHARS + "\n";
49
50   private static final String NONINTERLEAVED = 
51           "#MEGA\n"
52           + "!TITLE Noninterleaved sequence data\n\n" 
53           + "#U455  \n"
54           + "ABCFEDHIJ\n" 
55           + "MNOPQR\n\n" 
56           + "#CPZANT \n" 
57           + "KLMNOPWXYZ\n" 
58           + "CGATC\n";
59   
60   // this one starts interleaved then switches to non-interleaved
61   private static final String MIXED = 
62           "#MEGA\n"
63           + "!TITLE This is a mess\n\n" 
64           + "#CPZANT KLMNOPWXYZCGATC\n\n"
65           + "#U455\n  "
66           + "ABCFEDHIJ\n";
67
68   // interleaved with a new sequence appearing in the second block :-O
69   private static final String INTERLEAVED_SEQUENCE_ERROR = 
70           "#MEGA" + "\n"
71           + "!TITLE Interleaved sequence data\n\n"
72           + "#U455   ABCDEF\n" 
73           + "#CPZANT  MNOPQR\n\n"
74           + "#U456   KLMNOP\n";
75
76   // interleaved with description, bases/gaps in triplet groups
77   private static final String INTERLEAVED_WITH_DESCRIPTION = 
78           "#MEGA\n"
79           + "!Title Data with description;\n"
80           + "!Format DataType=DNA  indel=-\tCodeTable=Standard Missing=? MatchChar=.;\n\n"
81           + "!Description\n" 
82           + "    Line one of description\n"
83           + "    Line two of description;\n\n"
84           + "#U455   C-- GTA\n" 
85           + "#CPZANT ATC -G-\n\n"
86           + "#U455   CGA --T\n" 
87           + "#CPZANT CA- -GC\n";
88
89   //@formatter:on
90
91   /**
92    * Test parse of interleaved mega format data.
93    * 
94    * @throws IOException
95    */
96   @Test(groups = { "Functional" })
97   public void testParse_interleaved() throws IOException
98   {
99     MegaFile testee = new MegaFile(INTERLEAVED, AppletFormatAdapter.PASTE);
100     assertEquals("Title not as expected", "Interleaved sequence data",
101             testee.getAlignmentProperty(MegaFile.PROP_TITLE));
102     Vector<SequenceI> seqs = testee.getSeqs();
103     // should be 2 sequences
104     assertEquals("Expected two sequences", 2, seqs.size());
105     // check sequence names correct and order preserved
106     assertEquals("First sequence id wrong", "U455", seqs.get(0).getName());
107     assertEquals("Second sequence id wrong", "CPZANT", seqs.get(1)
108             .getName());
109     // check sequence data
110     assertEquals("First sequence data wrong", "ABCDEFKLMNOP", seqs.get(0)
111             .getSequenceAsString());
112     assertEquals("Second sequence data wrong", "MNOPQRWXYZGC", seqs.get(1)
113             .getSequenceAsString());
114     assertTrue("File format is not flagged as interleaved",
115             testee.isInterleaved());
116   }
117
118   /**
119    * Test parse of noninterleaved mega format data.
120    * 
121    * @throws IOException
122    */
123   @Test(groups = { "Functional" })
124   public void testParse_nonInterleaved() throws IOException
125   {
126     MegaFile testee = new MegaFile(NONINTERLEAVED,
127             AppletFormatAdapter.PASTE);
128     assertEquals("Title not as expected", "Noninterleaved sequence data",
129             testee.getAlignmentProperty(MegaFile.PROP_TITLE));
130     Vector<SequenceI> seqs = testee.getSeqs();
131     // should be 2 sequences
132     assertEquals("Expected two sequences", 2, seqs.size());
133     // check sequence names correct and order preserved
134     assertEquals("First sequence id wrong", "U455", seqs.get(0).getName());
135     assertEquals("Second sequence id wrong", "CPZANT", seqs.get(1)
136             .getName());
137     // check sequence data
138     assertEquals("First sequence data wrong", "ABCFEDHIJMNOPQR", seqs
139             .get(0).getSequenceAsString());
140     assertEquals("Second sequence data wrong", "KLMNOPWXYZCGATC",
141             seqs.get(1).getSequenceAsString());
142     assertFalse("File format is not flagged as noninterleaved",
143             testee.isInterleaved());
144   }
145
146   /**
147    * Test parsing an interleaved file with an extra sequence appearing after the
148    * first block - should fail.
149    */
150   @Test(groups = { "Functional" })
151   public void testParse_interleavedExtraSequenceError()
152   {
153     try
154     {
155       new MegaFile(INTERLEAVED_SEQUENCE_ERROR, AppletFormatAdapter.PASTE);
156       fail("Expected extra sequence IOException");
157     } catch (IOException e)
158     {
159       assertEquals(
160               "Unexpected exception message",
161               "Parse error: misplaced new sequence starting at #U456   KLMNOP",
162               e.getMessage());
163     }
164   }
165
166   /**
167    * Test a mixed up file.
168    */
169   @Test(groups = { "Functional" })
170   public void testParse_mixedInterleavedNonInterleaved()
171   {
172     try
173     {
174       new MegaFile(MIXED, AppletFormatAdapter.PASTE);
175       fail("Expected mixed content exception");
176     } catch (IOException e)
177     {
178       assertEquals(
179               "Unexpected exception message",
180               "Parse error: interleaved was true but now seems to be false, at line: ABCFEDHIJ",
181               e.getMessage());
182     }
183
184   }
185
186   @Test(groups = { "Functional" })
187   public void testGetSequenceId()
188   {
189     assertEquals("AB123", MegaFile.getSequenceId("#AB123 CGATC"));
190     assertEquals("AB123", MegaFile.getSequenceId("#AB123    CGATC"));
191     assertEquals("AB123", MegaFile.getSequenceId("#AB123 CGC TAC"));
192     assertEquals("AB123", MegaFile.getSequenceId("#AB123"));
193     assertNull(MegaFile.getSequenceId("AB123 CTAG"));
194     assertNull(MegaFile.getSequenceId("AB123"));
195     assertNull(MegaFile.getSequenceId(""));
196     assertNull(MegaFile.getSequenceId(null));
197   }
198
199   @Test(groups = { "Functional" })
200   public void testGetMaxIdLength()
201   {
202     SequenceI[] seqs = new Sequence[2];
203     seqs[0] = new Sequence("Something", "GCATAC");
204     seqs[1] = new Sequence("SomethingElse", "GCATAC");
205     assertEquals(13, MegaFile.getMaxIdLength(seqs));
206     seqs[1] = new Sequence("DNA", "GCATAC");
207     assertEquals(9, MegaFile.getMaxIdLength(seqs));
208   }
209
210   @Test(groups = { "Functional" })
211   public void testGetMaxSequenceLength()
212   {
213     SequenceI[] seqs = new Sequence[2];
214     seqs[0] = new Sequence("Seq1", "GCATAC");
215     seqs[1] = new Sequence("Seq2", "GCATACTAG");
216     assertEquals(9, MegaFile.getMaxSequenceLength(seqs));
217     seqs[1] = new Sequence("Seq2", "GCA");
218     assertEquals(6, MegaFile.getMaxSequenceLength(seqs));
219   }
220
221   /**
222    * Test (parse and) print of interleaved mega format data.
223    * 
224    * @throws IOException
225    */
226   @Test(groups = { "Functional" })
227   public void testPrint_interleaved() throws IOException
228   {
229     MegaFile testee = new MegaFile(INTERLEAVED, AppletFormatAdapter.PASTE);
230     String printed = testee.print();
231     System.out.println(printed);
232     // normally output should match input
233     // we cheated here with a number of short input lines
234     // nb don't get Title in output if not calling print(AlignmentI)
235     String expected = "#MEGA\n\n" + "#U455   ABCDEF [6]\n"
236             + "#CPZANT MNOPQR [6]\n\n" + "#U455   KLMNOP [12]\n"
237             + "#CPZANT WXYZGC [12]"
238             + "\n";
239     assertEquals("Print format wrong", expected, printed);
240   }
241
242   /**
243    * Test (parse and) print of interleaved data with no headers (acceptable).
244    * 
245    * @throws IOException
246    */
247   @Test(groups = { "Functional" })
248   public void testPrint_interleavedNoHeaders() throws IOException
249   {
250     MegaFile testee = new MegaFile(INTERLEAVED_NOHEADERS,
251             AppletFormatAdapter.PASTE);
252     String printed = testee.print();
253     System.out.println(printed);
254
255     //@formatter:off
256     assertEquals("Print format wrong", 
257     "#MEGA\n\n" + "#U455   ABCDEF [6]\n" 
258     + "#CPZANT MNOPQR [6]\n\n" 
259     + "#U455   KLMNOP [12]\n"
260     + "#CPZANT WXYZGC [12]\n",
261             printed);
262     //@formatter:on
263   }
264
265   /**
266    * Test (parse and) print of noninterleaved mega format data.
267    * 
268    * @throws IOException
269    */
270   @Test(groups = { "Functional" })
271   public void testPrint_noninterleaved() throws IOException
272   {
273     MegaFile testee = new MegaFile(NONINTERLEAVED,
274             AppletFormatAdapter.PASTE);
275     assertEquals(10, testee.getPositionsPerLine());
276     String printed = testee.print();
277     System.out.println(printed);
278     // normally output should match input
279     // we cheated here with a number of short input lines
280     String expected = "#MEGA\n\n"
281  + "#U455\n" + "ABCFEDHIJM\nNOPQR\n\n"
282             + "#CPZANT\n" + "KLMNOPWXYZ\nCGATC\n";
283     assertEquals("Print format wrong", expected, printed);
284   }
285
286   /**
287    * Test (parse and) print of interleaved mega format data extending to more
288    * than one line of output.
289    * 
290    * @throws IOException
291    */
292   @Test(groups = { "Functional" })
293   public void testPrint_interleavedMultiLine() throws IOException
294   {
295     MegaFile testee = new MegaFile(INTERLEAVED_50RESIDUES,
296             AppletFormatAdapter.PASTE);
297     assertEquals(50, testee.getPositionsPerLine());
298     /*
299      * now simulate choosing 20 residues per line on output
300      */
301     testee.setPositionsPerLine(20);
302     String printed = testee.print();
303     System.out.println(printed);
304     //@formatter:off
305     //0123456789klmnopqrstABCDEFGHIJ9876543210abcdefghij
306     String expected = 
307             "#MEGA\n\n" + 
308             "#U455   0123456789 klmnopqrst [20]\n" + // first 20
309             "#CPZANT 9876543210 abcdefghij [20]\n\n" +
310             "#U455   ABCDEFGHIJ 9876543210 [40]\n" + // next 20
311             "#CPZANT 0123456789 klmnopqrst [40]\n\n" +
312             "#U455   abcdefghij [50]\n" + // last 10
313             "#CPZANT ABCDEFGHIJ [50]\n";
314     //@formatter:on
315     assertEquals("Print format wrong", expected, printed);
316   }
317
318   /**
319    * Test (parse and) print of noninterleaved mega format data extending to more
320    * than one line of output.
321    * 
322    * @throws IOException
323    */
324   @Test(groups = { "Functional" })
325   public void testPrint_noninterleavedMultiLine() throws IOException
326   {
327     final String NONINTERLEAVED_LONGERTHAN50 = "#SIXTY\n" + THIRTY_CHARS
328             + "\n" + TWENTY_CHARS + "9993332221\n";
329     MegaFile testee = new MegaFile(NONINTERLEAVED_LONGERTHAN50,
330             AppletFormatAdapter.PASTE);
331     assertEquals(30, testee.getPositionsPerLine());
332     testee.setPositionsPerLine(25);
333     String printed = testee.print();
334     // 60 character sequence should be output as 50 on first line then 10 more
335     String expected = "#MEGA\n\n" + "#SIXTY\n"
336             + "0123456789klmnopqrstABCDE\n" + "FGHIJ9876543210abcdefghij\n"
337             + "9993332221\n";
338     assertEquals("Print format wrong", expected, printed);
339   }
340
341   /**
342    * Test parse of data including description
343    * 
344    * @throws IOException
345    */
346   @Test(groups = { "Functional" })
347   public void testParse_withDescription() throws IOException
348   {
349     MegaFile testee = new MegaFile(INTERLEAVED_WITH_DESCRIPTION,
350             AppletFormatAdapter.PASTE);
351     assertEquals("Title not as expected", "Data with description",
352             testee.getAlignmentProperty(MegaFile.PROP_TITLE));
353
354     Vector<SequenceI> seqs = testee.getSeqs();
355     // should be 2 sequences
356     assertEquals("Expected two sequences", 2, seqs.size());
357     // check sequence names correct and order preserved
358     assertEquals("First sequence id wrong", "U455", seqs.get(0).getName());
359     assertEquals("Second sequence id wrong", "CPZANT", seqs.get(1)
360             .getName());
361     // check sequence data
362     assertEquals("First sequence data wrong", "C--GTACGA--T", seqs.get(0)
363             .getSequenceAsString());
364     assertEquals("Second sequence data wrong", "ATC-G-CA--GC", seqs.get(1)
365             .getSequenceAsString());
366     assertTrue("File format is not flagged as interleaved",
367             testee.isInterleaved());
368
369     assertEquals(
370             "Description property not parsed",
371             "    Line one of description\n" + "    Line two of description",
372             testee.getAlignmentProperty(MegaFile.PROP_DESCRIPTION));
373   }
374
375   @Test(groups = { "Functional" })
376   public void testGetNonCommentContent() throws FileFormatException
377   {
378     assertEquals("abcde", MegaFile.getNonCommentContent("abcde", 0));
379     assertEquals("CGT ACG GAC ",
380             MegaFile.getNonCommentContent("CGT ACG GAC [9]", 0));
381     assertEquals("", MegaFile.getNonCommentContent("abcde", 1));
382     assertEquals(" abcde",
383             MegaFile.getNonCommentContent("and others ] abcde", 1));
384     assertEquals(" abcde", MegaFile.getNonCommentContent(
385             "and others [including refs] ] abcde", 1));
386     assertEquals(" x ] abcde",
387             MegaFile.getNonCommentContent("and others ] x ] abcde", 1));
388   }
389
390   @Test(groups = { "Functional" })
391   public void testCommentDepth() throws FileFormatException
392   {
393     assertEquals(0, MegaFile.commentDepth("abcde", 0));
394     assertEquals(1, MegaFile.commentDepth("abc[de", 0));
395     assertEquals(3, MegaFile.commentDepth("ab[c[de", 1));
396     assertEquals(1, MegaFile.commentDepth("ab]c[d]e[f", 1));
397     assertEquals(0, MegaFile.commentDepth("a]b[c]d]e", 1));
398   }
399
400   @Test(groups = { "Functional" })
401   public void testGetValue()
402   {
403     assertEquals("Mega", MegaFile.getValue("Name=Mega"));
404     assertEquals("Mega", MegaFile.getValue("Name =Mega"));
405     assertEquals("Mega", MegaFile.getValue(" Name = Mega "));
406     assertEquals("Mega", MegaFile.getValue("Name = Mega; "));
407     assertEquals("Mega", MegaFile.getValue(" Name = Mega ; "));
408     assertEquals("Mega", MegaFile.getValue("\t!Name \t= \tMega ; "));
409     assertEquals("Mega", MegaFile.getValue("!Name \t\t Mega; "));
410     assertEquals("", MegaFile.getValue("Name"));
411   }
412
413   /**
414    * Test reading a MEGA file to an alignment then writing it out in MEGA
415    * format. Verify the output is (functionally) the same as the input.
416    * 
417    * @throws IOException
418    */
419   @Test(groups = "Functional")
420   public void testRoundTrip_Interleaved() throws IOException
421   {
422     AppletFormatAdapter fa = new AppletFormatAdapter();
423     AlignmentI al = fa.readFile(INTERLEAVED_WITH_DESCRIPTION,
424             AppletFormatAdapter.PASTE, "MEGA");
425     MegaFile output = new MegaFile();
426     String formatted = output.print(al);
427     //@formatter:off
428     String expected = 
429          "#MEGA\n!Title Data with description;\n" +
430          "!Description\n" +
431          "    Line one of description\n" +
432          "    Line two of description;\n" +
433          "!Format\n" +
434          "    DataType=DNA CodeTable=Standard\n" +
435          "    NSeqs=2 NSites=12\n" + // NSites includes gaps
436          "    Indel=- Identical=. Missing=?;\n\n" +
437          "#U455   C-- GTA [6]\n" +
438          "#CPZANT ATC -G- [6]\n\n" +
439          "#U455   CGA --T [12]\n" +
440          "#CPZANT CA- -GC [12]\n";
441     //@formatter:on
442     assertEquals("Roundtrip didn't match", expected,
443             formatted);
444   }
445
446   /**
447    * Test reading a MEGA file to an alignment then writing it out in MEGA
448    * format. Verify the output is (functionally) the same as the input.
449    * 
450    * @throws IOException
451    */
452   @Test(groups = "Functional")
453   public void testRoundTrip_multilineFormatWithComments()
454           throws IOException
455   {
456     AppletFormatAdapter fa = new AppletFormatAdapter();
457     //@formatter:off
458     AlignmentI al = fa.readFile("#MEGA\n"
459     + "!Title Data with description;\n"
460     + "[ this comment should be ignored\n"
461     + "including [this nested comment]\n"
462     + "]\n"
463     + "!Format \n"
464     + "DataType=DNA CodeTable=Standard\n"
465     + "indel=- Missing=? MatchChar=.;\n\n"
466     + "!Description\n" 
467     + "    Line one of description\n"
468     + "    Line two of description;\n\n"
469     + "#U455   CGC GTA\n" 
470     + "#CPZANT ATC GGG\n\n"
471     + "#U455   CGA TTT\n" 
472     + "#CPZANT CAA TGC\n",
473             AppletFormatAdapter.PASTE, "MEGA");
474     //@formatter:on
475     MegaFile output = new MegaFile();
476     String formatted = output.print(al);
477     //@formatter:off
478     String expected = 
479          "#MEGA\n!Title Data with description;\n" +
480          "!Description\n" +
481          "    Line one of description\n" +
482          "    Line two of description;\n" +
483          "!Format\n" +
484          "    DataType=DNA CodeTable=Standard\n" +
485          "    NSeqs=2 NSites=12\n" +
486          "    Indel=- Identical=. Missing=?;\n\n" +
487          "#U455   CGC GTA [6]\n" +
488          "#CPZANT ATC GGG [6]\n\n" +
489          "#U455   CGA TTT [12]\n" +
490          "#CPZANT CAA TGC [12]\n";
491     //@formatter:on
492     assertEquals("Roundtrip didn't match", expected,
493             formatted);
494   }
495
496   //@formatter:on
497   
498   /**
499    * Test parse of interleaved mega format data where the identity character is
500    * used in sequences after the first
501    * 
502    * @throws IOException
503    */
504   @Test(groups = { "Functional" })
505   public void testParse_interleavedWithIdentity() throws IOException
506   {
507     //@formatter:off
508     MegaFile testee = new MegaFile("#MEGA\n"+ 
509     "!TITLE Interleaved sequence data;\n" +
510     "!Format Identical=.;\n\n" +
511     "#U455   ABCDEF\n" + 
512     "#CPZANT  M..P.R\n\n" + 
513     "#U455   KLMNOP\n" + 
514     "#CPZANT ..YZ..", AppletFormatAdapter.PASTE);
515     //@formatter:on
516     assertEquals("Title not as expected", "Interleaved sequence data",
517             testee.getAlignmentProperty(MegaFile.PROP_TITLE));
518     Vector<SequenceI> seqs = testee.getSeqs();
519     // should be 2 sequences
520     assertEquals("Expected two sequences", 2, seqs.size());
521     // check sequence names correct and order preserved
522     assertEquals("First sequence id wrong", "U455", seqs.get(0).getName());
523     assertEquals("Second sequence id wrong", "CPZANT", seqs.get(1)
524             .getName());
525     // check sequence data
526     assertEquals("First sequence data wrong", "ABCDEFKLMNOP", seqs.get(0)
527             .getSequenceAsString());
528     assertEquals("Second sequence data wrong", "MBCPERKLYZOP", seqs.get(1)
529             .getSequenceAsString());
530     assertTrue("File format is not flagged as interleaved",
531             testee.isInterleaved());
532   }
533
534   /**
535    * Test parse of noninterleaved format data including identity symbol
536    * 
537    * @throws IOException
538    */
539   @Test(groups = { "Functional" })
540   public void testParse_nonInterleavedWithIdentity() throws IOException
541   {
542     //@formatter:off
543     MegaFile testee = new MegaFile("#MEGA\n"
544     + "!TITLE Noninterleaved sequence data;\n"
545     + "!Format MatchChar=.;\n"
546     + "#U455  \n"
547     + "ABCFEDHIJ\n" 
548     + "MNOPQR\n\n" 
549     + "#CPZANT \n" 
550     + "KL..O..XYZ\n" 
551     + "CG..C\n",
552             AppletFormatAdapter.PASTE);
553     //@formatter:on
554     assertEquals("Title not as expected", "Noninterleaved sequence data",
555             testee.getAlignmentProperty(MegaFile.PROP_TITLE));
556     Vector<SequenceI> seqs = testee.getSeqs();
557     // should be 2 sequences
558     assertEquals("Expected two sequences", 2, seqs.size());
559     // check sequence names correct and order preserved
560     assertEquals("First sequence id wrong", "U455", seqs.get(0).getName());
561     assertEquals("Second sequence id wrong", "CPZANT", seqs.get(1)
562             .getName());
563     // check sequence data
564     assertEquals("First sequence data wrong", "ABCFEDHIJMNOPQR", seqs
565             .get(0).getSequenceAsString());
566     assertEquals("Second sequence data wrong", "KLCFODHXYZCGPQC",
567             seqs.get(1).getSequenceAsString());
568     assertFalse("File format is not flagged as noninterleaved",
569             testee.isInterleaved());
570   }
571
572   //@formatter:on
573   
574   /**
575    * Test parse of interleaved format data including position number comments.
576    * 
577    * @throws IOException
578    */
579   @Test(groups = { "Functional" })
580   public void testParse_interleavedWithPositionNumber() throws IOException
581   {
582     //@formatter:off
583     MegaFile testee = new MegaFile("#MEGA\n"+ 
584     "TITLE: Interleaved sequence data\n\n" + 
585     "#U455   ABCDEF [6]\n" + 
586     "#CPZANT  MNOPQR [6]\n\n" + 
587     "#U455   KLMNOP [12]\n" + 
588     "#CPZANT WXYZGC [12]\n", AppletFormatAdapter.PASTE);
589     //@formatter:on
590     assertEquals("Title not as expected", "Interleaved sequence data",
591             testee.getAlignmentProperty(MegaFile.PROP_TITLE));
592     Vector<SequenceI> seqs = testee.getSeqs();
593     // should be 2 sequences
594     assertEquals("Expected two sequences", 2, seqs.size());
595     // check sequence names correct and order preserved
596     assertEquals("First sequence id wrong", "U455", seqs.get(0).getName());
597     assertEquals("Second sequence id wrong", "CPZANT", seqs.get(1)
598             .getName());
599     // check sequence data
600     assertEquals("First sequence data wrong", "ABCDEFKLMNOP", seqs.get(0)
601             .getSequenceAsString());
602     assertEquals("Second sequence data wrong", "MNOPQRWXYZGC", seqs.get(1)
603             .getSequenceAsString());
604     assertTrue("File format is not flagged as interleaved",
605             testee.isInterleaved());
606   }
607
608   //@formatter:on
609   
610   /**
611    * Test parse of data with !Gene and !Domain statements.
612    * 
613    * @throws IOException
614    */
615   @Test(groups = { "Functional" })
616   public void testParse_geneDomains() throws IOException
617   {
618     //@formatter:off
619     String data = "#MEGA\n"+ 
620     "TITLE: Interleaved sequence data\n\n" + 
621     "#U455   CCCCCC\n" + 
622     "#CPZANT  TTTTTT\n\n" +
623     "!Domain=Exon1 Gene=Adh Property=Coding CodonStart=1;\n" +
624     "#U455   GGGGGG\n" + 
625     "#CPZANT AAAAAA\n\n" +
626     "!Domain=Intron1 Property=Intron Gene=Adh;\n" +
627     "#U455   tttttt\n" + 
628     "#CPZANT cccccc\n\n" +
629     "!Domain=Exon2 Gene=Adh Property=Exon CodonStart=1;\n" +
630     "#U455   aaaaaa\n" + 
631     "#CPZANT gggggg\n\n" +
632     // explicit end of Exon2, implicit end of Adh:
633     "!Domain=Exon2 Property=domainend;\n" +
634     "!Domain=Intron1 Gene=Opsin Property=Noncoding;\n" +
635     "#U455   GGGGGG\n" + 
636     "#CPZANT AAAAAA\n\n" +
637     // end Opsin, start MEF2A
638     "!Domain=Exon1 Gene=MEF2A Property=Coding CodonStart=1;\n" +
639     "#U455   tttttt\n" + 
640     "#CPZANT cccccc\n\n" +
641     // end MEF2A
642     "!Domain=BindingSite;\n" +
643     "#U455   CCCCCC\n" + 
644     "#CPZANT TTTTTT\n\n";
645     //@formatter:on
646     MegaFile testee = new MegaFile(data, AppletFormatAdapter.PASTE);
647
648     Vector<SequenceI> seqs = testee.getSeqs();
649     // should be 2 sequences
650     assertEquals("Expected two sequences", 2, seqs.size());
651     // check sequence data
652     assertEquals("First sequence data wrong",
653             "CCCCCCGGGGGGttttttaaaaaaGGGGGGttttttCCCCCC", seqs.get(0)
654             .getSequenceAsString());
655     assertEquals("Second sequence data wrong",
656             "TTTTTTAAAAAAccccccggggggAAAAAAccccccTTTTTT", seqs.get(1)
657             .getSequenceAsString());
658
659     /*
660      * sequences should have features for Gene=Adh 7-24, Exon1 7-12, Intron1
661      * 13-18, Exon2 19-24, BindingSite 25-30
662      */
663     for (SequenceI seq : seqs) {
664       SequenceFeature[] sfs = seq.getSequenceFeatures();
665       // features are added in the order in which their end is found
666       // (Domain before Gene when they end together)
667       assertEquals(9, sfs.length);
668       // TODO settle which way round type/description go!
669       assertEquals("Exon1 (Adh Coding)", sfs[0].type);
670       assertEquals("Domain", sfs[0].description);
671       assertEquals(7, sfs[0].begin);
672       assertEquals(12, sfs[0].end);
673       assertEquals("Intron1 (Adh Noncoding)", sfs[1].type);
674       assertEquals("Domain", sfs[1].description);
675       assertEquals(13, sfs[1].begin);
676       assertEquals(18, sfs[1].end);
677       assertEquals("Exon2 (Adh Coding)", sfs[2].type);
678       assertEquals("Domain", sfs[2].description);
679       assertEquals(19, sfs[2].begin);
680       assertEquals(24, sfs[2].end);
681       assertEquals("Adh", sfs[3].type);
682       assertEquals("Gene", sfs[3].description);
683       assertEquals(7, sfs[3].begin);
684       assertEquals(24, sfs[3].end);
685       assertEquals("Intron1 (Opsin Noncoding)", sfs[4].type);
686       assertEquals("Domain", sfs[4].description);
687       assertEquals(25, sfs[4].begin);
688       assertEquals(30, sfs[4].end);
689       assertEquals("Opsin", sfs[5].type);
690       assertEquals("Gene", sfs[5].description);
691       assertEquals(25, sfs[5].begin);
692       assertEquals(30, sfs[5].end);
693       assertEquals("Exon1 (MEF2A Coding)", sfs[6].type);
694       assertEquals("Domain", sfs[6].description);
695       assertEquals(31, sfs[6].begin);
696       assertEquals(36, sfs[6].end);
697       assertEquals("MEF2A", sfs[7].type);
698       assertEquals("Gene", sfs[7].description);
699       assertEquals(31, sfs[7].begin);
700       assertEquals(36, sfs[7].end);
701       assertEquals("BindingSite", sfs[8].type);
702       assertEquals("Domain", sfs[8].description);
703       assertEquals(37, sfs[8].begin);
704       assertEquals(42, sfs[8].end);
705     }
706   }
707 }