Merge branch 'develop' into features/JAL-845splitPaneMergeDevelop
[jalview.git] / test / jalview / analysis / AlignmentUtilsTests.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3  * Copyright (C) 2014 The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.analysis;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertSame;
25 import static org.junit.Assert.assertTrue;
26 import jalview.analysis.AlignmentUtils.MappingResult;
27 import jalview.datamodel.AlignedCodonFrame;
28 import jalview.datamodel.Alignment;
29 import jalview.datamodel.AlignmentI;
30 import jalview.datamodel.Mapping;
31 import jalview.datamodel.Sequence;
32 import jalview.datamodel.SequenceI;
33 import jalview.io.AppletFormatAdapter;
34 import jalview.io.FormatAdapter;
35 import jalview.util.MapList;
36
37 import java.io.IOException;
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.Map;
42
43 import org.junit.Test;
44
45 public class AlignmentUtilsTests 
46 {
47   // @formatter:off
48   private static final String TEST_DATA = 
49           "# STOCKHOLM 1.0\n" +
50           "#=GS D.melanogaster.1 AC AY119185.1/838-902\n" +
51           "#=GS D.melanogaster.2 AC AC092237.1/57223-57161\n" +
52           "#=GS D.melanogaster.3 AC AY060611.1/560-627\n" +
53           "D.melanogaster.1          G.AGCC.CU...AUGAUCGA\n" +
54           "#=GR D.melanogaster.1 SS  ................((((\n" +
55           "D.melanogaster.2          C.AUUCAACU.UAUGAGGAU\n" +
56           "#=GR D.melanogaster.2 SS  ................((((\n" +
57           "D.melanogaster.3          G.UGGCGCU..UAUGACGCA\n" +
58           "#=GR D.melanogaster.3 SS  (.(((...(....(((((((\n" +
59           "//";
60
61   private static final String AA_SEQS_1 = 
62           ">Seq1Name\n" +
63           "K-QY--L\n" +
64           ">Seq2Name\n" +
65           "-R-FP-W-\n";
66
67   private static final String CDNA_SEQS_1 = 
68           ">Seq1Name\n" +
69           "AC-GG--CUC-CAA-CT\n" +
70           ">Seq2Name\n" +
71           "-CG-TTA--ACG---AAGT\n";
72
73   private static final String CDNA_SEQS_2 = 
74           ">Seq1Name\n" +
75           "GCTCGUCGTACT\n" +
76           ">Seq2Name\n" +
77           "GGGTCAGGCAGT\n";
78   // @formatter:on
79
80   public static Sequence ts=new Sequence("short","ASDASDASDASDASDASDASDASDASDASDASDASDASD");
81
82   @Test
83   public void testExpandFlanks()
84   {
85     AlignmentI al = new Alignment(new Sequence[] {});
86     for (int i=4;i<14;i+=3)
87     {
88       SequenceI s1=ts.deriveSequence().getSubSequence(i, i+7);
89       al.addSequence(s1);
90     }
91     System.out.println(new AppletFormatAdapter().formatSequences("Clustal", al, true));
92     for (int flnk=-1;flnk<25; flnk++)
93     {
94       AlignmentI exp;
95       System.out.println("\nFlank size: "+flnk);
96       System.out.println(new AppletFormatAdapter().formatSequences("Clustal", exp=AlignmentUtils.expandContext(al, flnk), true));
97       if (flnk==-1) {
98         for (SequenceI sq:exp.getSequences())
99       {
100           String ung = sq.getSequenceAsString().replaceAll("-+", "");
101           assertTrue("Flanking sequence not the same as original dataset sequence.\n"+ung+"\n"+sq.getDatasetSequence().getSequenceAsString(),ung.equalsIgnoreCase(sq.getDatasetSequence().getSequenceAsString()));
102       }
103       }
104     }
105     }    
106
107   /**
108    * Test method that returns a map of lists of sequences by sequence name.
109    * 
110    * @throws IOException
111    */
112   @Test
113   public void testGetSequencesByName() throws IOException
114   {
115     final String data = ">Seq1Name\nKQYL\n" + ">Seq2Name\nRFPW\n"
116             + ">Seq1Name\nABCD\n";
117     AlignmentI al = loadAlignment(data, "FASTA");
118     Map<String, List<SequenceI>> map = AlignmentUtils
119             .getSequencesByName(al);
120     assertEquals(2, map.keySet().size());
121     assertEquals(2, map.get("Seq1Name").size());
122     assertEquals("KQYL", map.get("Seq1Name").get(0).getSequenceAsString());
123     assertEquals("ABCD", map.get("Seq1Name").get(1).getSequenceAsString());
124     assertEquals(1, map.get("Seq2Name").size());
125     assertEquals("RFPW", map.get("Seq2Name").get(0).getSequenceAsString());
126   }
127   /**
128    * Helper method to load an alignment and ensure dataset sequences are set up.
129    * 
130    * @param data
131    * @param format TODO
132    * @return
133    * @throws IOException
134    */
135   protected AlignmentI loadAlignment(final String data, String format) throws IOException
136   {
137     Alignment a = new FormatAdapter().readFile(data,
138             AppletFormatAdapter.PASTE, format);
139     a.setDataset(null);
140     return a;
141   }
142   /**
143    * Test mapping of protein to cDNA.
144    * 
145    * @throws IOException
146    */
147   @Test
148   public void testMapProteinToCdna() throws IOException
149   {
150     // protein: Human + Mouse, 3 residues
151     AlignmentI protein = loadAlignment(
152             ">Human\nKQY\n>Mouse\nAFP\n>Worm\nRST\n",
153             "FASTA");
154     // cDNA: Mouse, Human, Mouse, 9 bases
155     // @formatter:off
156     String dnaData = 
157             ">Mouse\nGAAATCCAG\n" + 
158             ">Human\nTTCGATTAC\n" + 
159             ">Mouse\nGTCGTTTGC\n" + 
160             ">Mouse\nGTCGTTTGCgac\n" + // not mapped - wrong length 
161             ">Fly\nGTCGTTTGC\n"; // not mapped - no name match
162     // @formatter:on
163     AlignmentI cdna1 = loadAlignment(
164             dnaData,
165             "FASTA");
166     MappingResult mapped = AlignmentUtils.mapProteinToCdna(protein, cdna1);
167     assertEquals(mapped, MappingResult.Mapped);
168
169     /*
170      * Check two mappings (one for Mouse, one for Human)
171      */
172     assertEquals(2, protein.getCodonFrames().size());
173     assertEquals(1, protein.getCodonFrame(protein.getSequenceAt(0)).size());
174     assertEquals(1, protein.getCodonFrame(protein.getSequenceAt(1)).size());
175
176     /*
177      * Inspect mapping for Human protein
178      */
179     AlignedCodonFrame humanMapping = protein.getCodonFrame(
180             protein.getSequenceAt(0)).get(0);
181     assertEquals(1, humanMapping.getdnaSeqs().length);
182     assertEquals(cdna1.getSequenceAt(1).getDatasetSequence(),
183             humanMapping.getdnaSeqs()[0]);
184     Mapping[] protMappings = humanMapping.getProtMappings();
185     assertEquals(1, protMappings.length);
186     MapList mapList = protMappings[0].getMap();
187     assertEquals(3, mapList.getFromRatio());
188     assertEquals(1, mapList.getToRatio());
189     assertTrue(Arrays.equals(new int[]
190     { 1, 9 }, mapList.getFromRanges().get(0)));
191     assertEquals(1, mapList.getFromRanges().size());
192     assertTrue(Arrays.equals(new int[]
193     { 1, 3 }, mapList.getToRanges().get(0)));
194     assertEquals(1, mapList.getToRanges().size());
195
196     /*
197      * Inspect mappings for Mouse protein
198      */
199     AlignedCodonFrame mouseMapping1 = protein.getCodonFrame(
200             protein.getSequenceAt(1)).get(0);
201     assertEquals(2, mouseMapping1.getdnaSeqs().length);
202     assertEquals(cdna1.getSequenceAt(0).getDatasetSequence(),
203             mouseMapping1.getdnaSeqs()[0]);
204     assertEquals(cdna1.getSequenceAt(2).getDatasetSequence(),
205             mouseMapping1.getdnaSeqs()[1]);
206     protMappings = mouseMapping1.getProtMappings();
207     assertEquals(2, protMappings.length);
208     for (int i = 0; i < 2; i++)
209     {
210       mapList = protMappings[i].getMap();
211       assertEquals(3, mapList.getFromRatio());
212       assertEquals(1, mapList.getToRatio());
213       assertTrue(Arrays.equals(new int[]
214       { 1, 9 }, mapList.getFromRanges().get(0)));
215       assertEquals(1, mapList.getFromRanges().size());
216       assertTrue(Arrays.equals(new int[]
217       { 1, 3 }, mapList.getToRanges().get(0)));
218       assertEquals(1, mapList.getToRanges().size());
219     }
220   }
221
222   /**
223    * Test mapping of protein to cDNA which may include start and/or stop codons.
224    * 
225    * @throws IOException
226    */
227   @Test
228   public void testMapProteinToCdna_stopStartCodons() throws IOException
229   {
230     // protein: Human + Mouse, 3 residues
231     AlignmentI protein = loadAlignment(
232             ">Human\nKQY\n>Mouse\nAFP\n>Worm\nRST\n", "FASTA");
233     // @formatter:off
234     String dnaData = 
235             ">Mouse\natgGAAATCCAG\n" + // Mouse with start codon
236             ">Human\nTTCGATtactaa\n" + // Human with stop codon TAA
237             ">Mouse\nGTCGTTTGctaG\n" + // Mouse with stop codon TAG 
238             ">Human\nGTCGTTTgctGa\n" + // Human with stop codon TGA
239             ">Mouse\nATGGTCGTTTGCtag\n"; // Mouse with start and stop codons 
240     // @formatter:on
241     AlignmentI cdna1 = loadAlignment(
242             dnaData,
243             "FASTA");
244     MappingResult mapped = AlignmentUtils.mapProteinToCdna(protein, cdna1);
245     assertEquals(mapped, MappingResult.Mapped);
246
247     /*
248      * Check two mappings (one for Mouse, one for Human)
249      */
250     assertEquals(2, protein.getCodonFrames().size());
251     assertEquals(1, protein.getCodonFrame(protein.getSequenceAt(0)).size());
252     assertEquals(1, protein.getCodonFrame(protein.getSequenceAt(1)).size());
253
254     /*
255      * Inspect mapping for Human protein - should map to 2nd and 4th cDNA seqs
256      */
257     AlignedCodonFrame humanMapping = protein.getCodonFrame(
258             protein.getSequenceAt(0)).get(0);
259     assertEquals(2, humanMapping.getdnaSeqs().length);
260     assertEquals(cdna1.getSequenceAt(1).getDatasetSequence(),
261             humanMapping.getdnaSeqs()[0]);
262     assertEquals(cdna1.getSequenceAt(3).getDatasetSequence(),
263             humanMapping.getdnaSeqs()[1]);
264     Mapping[] protMappings = humanMapping.getProtMappings();
265     // two mappings, both to cDNA with stop codon
266     assertEquals(2, protMappings.length);
267
268     MapList mapList = protMappings[0].getMap();
269     assertEquals(3, mapList.getFromRatio());
270     assertEquals(1, mapList.getToRatio());
271     assertTrue(Arrays.equals(new int[]
272     { 1, 9 }, mapList.getFromRanges().get(0)));
273     assertEquals(1, mapList.getFromRanges().size());
274     assertTrue(Arrays.equals(new int[]
275     { 1, 3 }, mapList.getToRanges().get(0)));
276     assertEquals(1, mapList.getToRanges().size());
277
278     mapList = protMappings[1].getMap();
279     assertEquals(3, mapList.getFromRatio());
280     assertEquals(1, mapList.getToRatio());
281     assertTrue(Arrays.equals(new int[]
282     { 1, 9 }, mapList.getFromRanges().get(0)));
283     assertEquals(1, mapList.getFromRanges().size());
284     assertTrue(Arrays.equals(new int[]
285     { 1, 3 }, mapList.getToRanges().get(0)));
286     assertEquals(1, mapList.getToRanges().size());
287
288     /*
289      * Inspect mapping for Mouse protein - should map to 1st/3rd/5th cDNA seqs
290      */
291     AlignedCodonFrame mouseMapping = protein.getCodonFrame(
292             protein.getSequenceAt(1)).get(0);
293     assertEquals(3, mouseMapping.getdnaSeqs().length);
294     assertEquals(cdna1.getSequenceAt(0).getDatasetSequence(),
295             mouseMapping.getdnaSeqs()[0]);
296     assertEquals(cdna1.getSequenceAt(2).getDatasetSequence(),
297             mouseMapping.getdnaSeqs()[1]);
298     assertEquals(cdna1.getSequenceAt(4).getDatasetSequence(),
299             mouseMapping.getdnaSeqs()[2]);
300
301     // three mappings
302     protMappings = mouseMapping.getProtMappings();
303     assertEquals(3, protMappings.length);
304
305     // first mapping to cDNA with start codon
306     mapList = protMappings[0].getMap();
307     assertEquals(3, mapList.getFromRatio());
308     assertEquals(1, mapList.getToRatio());
309     assertTrue(Arrays.equals(new int[]
310     { 4, 12 }, mapList.getFromRanges().get(0)));
311     assertEquals(1, mapList.getFromRanges().size());
312     assertTrue(Arrays.equals(new int[]
313     { 1, 3 }, mapList.getToRanges().get(0)));
314     assertEquals(1, mapList.getToRanges().size());
315
316     // second mapping to cDNA with stop codon
317     mapList = protMappings[1].getMap();
318     assertEquals(3, mapList.getFromRatio());
319     assertEquals(1, mapList.getToRatio());
320     assertTrue(Arrays.equals(new int[]
321     { 1, 9 }, mapList.getFromRanges().get(0)));
322     assertEquals(1, mapList.getFromRanges().size());
323     assertTrue(Arrays.equals(new int[]
324     { 1, 3 }, mapList.getToRanges().get(0)));
325     assertEquals(1, mapList.getToRanges().size());
326
327     // third mapping to cDNA with start and stop codon
328     mapList = protMappings[2].getMap();
329     assertEquals(3, mapList.getFromRatio());
330     assertEquals(1, mapList.getToRatio());
331     assertTrue(Arrays.equals(new int[]
332     { 4, 12 }, mapList.getFromRanges().get(0)));
333     assertEquals(1, mapList.getFromRanges().size());
334     assertTrue(Arrays.equals(new int[]
335     { 1, 3 }, mapList.getToRanges().get(0)));
336     assertEquals(1, mapList.getToRanges().size());
337   }
338
339   /**
340    * Test for the alignSequenceAs method that takes two sequences and a mapping.
341    */
342   @Test
343   public void testAlignSequenceAs_withMapping_noIntrons()
344   {
345     MapList map = new MapList(new int[]
346     { 1, 6 }, new int[]
347     { 1, 2 }, 3, 1);
348
349     /*
350      * No existing gaps in dna:
351      */
352     checkAlignSequenceAs("GGGAAA", "-A-L-", false, false, map,
353             "---GGG---AAA");
354
355     /*
356      * Now introduce gaps in dna but ignore them when realigning.
357      */
358     checkAlignSequenceAs("-G-G-G-A-A-A-", "-A-L-", false, false, map,
359             "---GGG---AAA");
360
361     /*
362      * Now include gaps in dna when realigning. First retaining 'mapped' gaps
363      * only, i.e. those within the exon region.
364      */
365     checkAlignSequenceAs("-G-G--G-A--A-A-", "-A-L-", true, false, map,
366             "---G-G--G---A--A-A");
367
368     /*
369      * Include all gaps in dna when realigning (within and without the exon
370      * region). The leading gap, and the gaps between codons, are subsumed by
371      * the protein alignment gap.
372      */
373     checkAlignSequenceAs("-G-GG--AA-A-", "-A-L-", true, true, map,
374             "---G-GG---AA-A-");
375
376     /*
377      * Include only unmapped gaps in dna when realigning (outside the exon
378      * region). The leading gap, and the gaps between codons, are subsumed by
379      * the protein alignment gap.
380      */
381     checkAlignSequenceAs("-G-GG--AA-A-", "-A-L-", false, true, map,
382             "---GGG---AAA-");
383   }
384
385   /**
386    * Test for the alignSequenceAs method that takes two sequences and a mapping.
387    */
388   @Test
389   public void testAlignSequenceAs_withMapping_withIntrons()
390   {
391     /*
392      * Exons at codon 2 (AAA) and 4 (TTT)
393      */
394     MapList map = new MapList(new int[]
395     { 4, 6, 10, 12 }, new int[]
396     { 1, 2 }, 3, 1);
397
398     /*
399      * Simple case: no gaps in dna
400      */
401     checkAlignSequenceAs("GGGAAACCCTTTGGG", "--A-L-", false, false, map,
402             "GGG---AAACCCTTTGGG");
403
404     /*
405      * Add gaps to dna - but ignore when realigning.
406      */
407     checkAlignSequenceAs("-G-G-G--A--A---AC-CC-T-TT-GG-G-", "--A-L-",
408             false, false, map, "GGG---AAACCCTTTGGG");
409
410     /*
411      * Add gaps to dna - include within exons only when realigning.
412      */
413     checkAlignSequenceAs("-G-G-G--A--A---A-C-CC-T-TT-GG-G-", "--A-L-",
414             true, false, map, "GGG---A--A---ACCCT-TTGGG");
415
416     /*
417      * Include gaps outside exons only when realigning.
418      */
419     checkAlignSequenceAs("-G-G-G--A--A---A-C-CC-T-TT-GG-G-", "--A-L-",
420             false, true, map, "-G-G-GAAAC-CCTTT-GG-G-");
421
422     /*
423      * Include gaps following first intron if we are 'preserving mapped gaps'
424      */
425     checkAlignSequenceAs("-G-G-G--A--A---A-C-CC-T-TT-GG-G-", "--A-L-",
426             true, true, map, "-G-G-G--A--A---A-C-CC-T-TT-GG-G-");
427
428     /*
429      * Include all gaps in dna when realigning.
430      */
431     checkAlignSequenceAs("-G-G-G--A--A---A-C-CC-T-TT-GG-G-", "--A-L-",
432             true, true, map, "-G-G-G--A--A---A-C-CC-T-TT-GG-G-");
433   }
434
435   /**
436    * Test for the case where not all of the protein sequence is mapped to cDNA.
437    */
438   @Test
439   public void testAlignSequenceAs_withMapping_withUnmappedProtein()
440   {
441     
442     /*
443      * Exons at codon 2 (AAA) and 4 (TTT) mapped to A and P
444      */
445     final MapList map = new MapList(new int[]
446     { 4, 6, 10, 12 }, new int[]
447     { 1, 1, 3, 3 }, 3, 1);
448     
449
450     /*
451      * Expect alignment does nothing (aborts realignment). Change this test
452      * first if different behaviour wanted.
453      */
454     checkAlignSequenceAs("GGGAAACCCTTTGGG", "-A-L-P-", false,
455             false, map, "GGGAAACCCTTTGGG");
456   }
457
458   /**
459    * Helper method that performs and verifies the method under test.
460    * 
461    * @param dnaSeq
462    * @param proteinSeq
463    * @param preserveMappedGaps
464    * @param preserveUnmappedGaps
465    * @param map
466    * @param expected
467    */
468   protected void checkAlignSequenceAs(final String dnaSeq,
469           final String proteinSeq, final boolean preserveMappedGaps,
470           final boolean preserveUnmappedGaps, MapList map,
471           final String expected)
472   {
473     SequenceI dna = new Sequence("Seq1", dnaSeq);
474     dna.createDatasetSequence();
475     SequenceI protein = new Sequence("Seq1", proteinSeq);
476     protein.createDatasetSequence();
477     AlignedCodonFrame acf = new AlignedCodonFrame();
478     acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
479
480     AlignmentUtils.alignSequenceAs(dna, protein, acf, "---", '-',
481             preserveMappedGaps, preserveUnmappedGaps);
482     assertEquals(expected, dna.getSequenceAsString());
483   }
484
485   /**
486    * Test for the alignSequenceAs method where we preserve gaps in introns only.
487    */
488   @Test
489   public void testAlignSequenceAs_keepIntronGapsOnly()
490   {
491
492     /*
493      * Intron GGGAAA followed by exon CCCTTT
494      */
495     MapList map = new MapList(new int[]
496     { 7, 12 }, new int[]
497     { 1, 2 }, 3, 1);
498     
499     checkAlignSequenceAs("GG-G-AA-A-C-CC-T-TT", "AL",
500             false, true, map, "GG-G-AA-ACCCTTT");
501   }
502
503   /**
504    * Test for the method that generates an aligned translated sequence from one
505    * mapping.
506    */
507   @Test
508   public void testGetAlignedTranslation_dnaLikeProtein()
509   {
510     // dna alignment will be replaced
511     SequenceI dna = new Sequence("Seq1", "T-G-CC-A--T-TAC-CAG-");
512     dna.createDatasetSequence();
513     // protein alignment will be 'applied' to dna
514     SequenceI protein = new Sequence("Seq1", "-CH-Y--Q-");
515     protein.createDatasetSequence();
516     MapList map = new MapList(new int[]
517     { 1, 12 }, new int[]
518     { 1, 4 }, 3, 1);
519     AlignedCodonFrame acf = new AlignedCodonFrame();
520     acf.addMap(dna.getDatasetSequence(), protein.getDatasetSequence(), map);
521
522     final SequenceI aligned = AlignmentUtils
523                 .getAlignedTranslation(protein, '-', acf);
524     assertEquals("---TGCCAT---TAC------CAG---", aligned.getSequenceAsString());
525     assertSame(aligned.getDatasetSequence(), dna.getDatasetSequence());
526   }
527
528   /**
529    * Test the method that realigns protein to match mapped codon alignment.
530    */
531   @Test
532   public void testAlignProteinAsDna()
533   {
534     // seq1 codons are [1,2,3] [4,5,6] [7,8,9] [10,11,12]
535     SequenceI dna1 = new Sequence("Seq1", "TGCCATTACCAG-");
536     // seq2 codons are [1,3,4] [5,6,7] [8,9,10] [11,12,13]
537     SequenceI dna2 = new Sequence("Seq2", "T-GCCATTACCAG");
538     // seq3 codons are [1,2,3] [4,5,7] [8,9,10] [11,12,13]
539     SequenceI dna3 = new Sequence("Seq3", "TGCCA-TTACCAG");
540     AlignmentI dna = new Alignment(new SequenceI[]
541     { dna1, dna2, dna3 });
542     dna.setDataset(null);
543
544     // protein alignment will be realigned like dna
545     SequenceI prot1 = new Sequence("Seq1", "CHYQ");
546     SequenceI prot2 = new Sequence("Seq2", "CHYQ");
547     SequenceI prot3 = new Sequence("Seq3", "CHYQ");
548     AlignmentI protein = new Alignment(new SequenceI[]
549     { prot1, prot2, prot3 });
550     protein.setDataset(null);
551
552     MapList map = new MapList(new int[]
553     { 1, 12 }, new int[]
554     { 1, 4 }, 3, 1);
555     AlignedCodonFrame acf = new AlignedCodonFrame();
556     acf.addMap(dna1.getDatasetSequence(), prot1.getDatasetSequence(), map);
557     acf.addMap(dna2.getDatasetSequence(), prot2.getDatasetSequence(), map);
558     acf.addMap(dna3.getDatasetSequence(), prot3.getDatasetSequence(), map);
559     protein.setCodonFrames(Collections.singleton(acf));
560
561     /*
562      * Translated codon order is [1,2,3] [1,3,4] [4,5,6] [4,5,7] [5,6,7] [7,8,9]
563      * [8,9,10] [10,11,12] [11,12,13]
564      */
565     AlignmentUtils.alignProteinAsDna(protein, dna);
566     assertEquals("C-H--Y-Q-", prot1.getSequenceAsString());
567     assertEquals("-C--H-Y-Q", prot2.getSequenceAsString());
568     assertEquals("C--H--Y-Q", prot3.getSequenceAsString());
569   }
570
571 }