29cf9c9721d532da3d3ce1e4aeb0075997361dcc
[jalview.git] / test / jalview / io / vcf / VCFLoaderTest.java
1 package jalview.io.vcf;
2
3 import static org.testng.Assert.assertEquals;
4
5 import jalview.bin.Cache;
6 import jalview.datamodel.AlignmentI;
7 import jalview.datamodel.DBRefEntry;
8 import jalview.datamodel.Mapping;
9 import jalview.datamodel.Sequence;
10 import jalview.datamodel.SequenceFeature;
11 import jalview.datamodel.SequenceI;
12 import jalview.datamodel.features.SequenceFeatures;
13 import jalview.gui.AlignFrame;
14 import jalview.io.DataSourceType;
15 import jalview.io.FileLoader;
16 import jalview.io.gff.Gff3Helper;
17 import jalview.io.gff.SequenceOntologyI;
18 import jalview.util.MapList;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.io.PrintWriter;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.testng.annotations.BeforeClass;
27 import org.testng.annotations.Test;
28
29 public class VCFLoaderTest
30 {
31   private static final float DELTA = 0.00001f;
32
33   // columns 9717- of gene P30419 from Ensembl (much modified)
34   private static final String FASTA = ""
35           +
36           /*
37            * forward strand 'gene' and 'transcript' with two exons
38            */
39           ">gene1/1-25 chromosome:GRCh38:17:45051610:45051634:1\n"
40           + "CAAGCTGGCGGACGAGAGTGTGACA\n"
41           + ">transcript1/1-18\n--AGCTGGCG----AGAGTGTGAC-\n"
42
43           /*
44            * reverse strand gene and transcript (reverse complement alleles!)
45            */
46           + ">gene2/1-25 chromosome:GRCh38:17:45051610:45051634:-1\n"
47           + "TGTCACACTCTCGTCCGCCAGCTTG\n"
48           + ">transcript2/1-18\n" + "-GTCACACTCT----CGCCAGCT--\n"
49
50           /*
51            * 'gene' on chromosome 5 with two transcripts
52            */
53           + ">gene3/1-25 chromosome:GRCh38:5:45051610:45051634:1\n"
54           + "CAAGCTGGCGGACGAGAGTGTGACA\n"
55           + ">transcript3/1-18\n--AGCTGGCG----AGAGTGTGAC-\n"
56           + ">transcript4/1-18\n-----TGG-GGACGAGAGTGTGA-A\n";
57
58   private static final String[] VCF = { "##fileformat=VCFv4.2",
59       "##INFO=<ID=AF,Number=A,Type=Float,Description=\"Allele Frequency, for each ALT allele, in the same order as listed\">",
60       "##reference=Homo_sapiens/GRCh38",
61       "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO",
62       // A/T,C variants in position 2 of gene sequence (precedes transcript)
63       // should create 2 variant features with respective scores
64       "17\t45051611\t.\tA\tT,C\t1666.64\tRF\tAC=15;AF=5.0e-03,4.0e-03",
65       // SNP G/C in position 4 of gene sequence, position 2 of transcript
66       // insertion G/GA is transferred to nucleotide but not to peptide
67       "17\t45051613\t.\tG\tGA,C\t1666.64\tRF\tAC=15;AF=3.0e-03,2.0e-03" };
68
69   @BeforeClass
70   public void setUp()
71   {
72     /*
73      * configure to capture all available VCF and VEP (CSQ) fields
74      */
75     Cache.loadProperties("test/jalview/io/testProps.jvprops");
76     Cache.setProperty("VCF_FIELDS", ".*");
77     Cache.setProperty("VEP_FIELDS", ".*");
78   }
79
80   @Test(groups = "Functional")
81   public void testDoLoad() throws IOException
82   {
83     AlignmentI al = buildAlignment();
84     VCFLoader loader = new VCFLoader(al);
85
86     File f = makeVcf();
87
88     loader.doLoad(f.getPath(), null);
89
90     /*
91      * verify variant feature(s) added to gene
92      * NB alleles at a locus may not be processed, and features added,
93      * in the order in which they appear in the VCF record as method
94      * VariantContext.getAlternateAlleles() does not guarantee order
95      * - order of assertions here matches what we find (is not important) 
96      */
97     List<SequenceFeature> geneFeatures = al.getSequenceAt(0)
98             .getSequenceFeatures();
99     SequenceFeatures.sortFeatures(geneFeatures, true);
100     assertEquals(geneFeatures.size(), 4);
101     SequenceFeature sf = geneFeatures.get(0);
102     assertEquals(sf.getFeatureGroup(), "VCF");
103     assertEquals(sf.getBegin(), 2);
104     assertEquals(sf.getEnd(), 2);
105     assertEquals(sf.getScore(), 4.0e-03, DELTA);
106     assertEquals(sf.getValue(Gff3Helper.ALLELES), "A,C");
107     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
108     sf = geneFeatures.get(1);
109     assertEquals(sf.getFeatureGroup(), "VCF");
110     assertEquals(sf.getBegin(), 2);
111     assertEquals(sf.getEnd(), 2);
112     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
113     assertEquals(sf.getScore(), 5.0e-03, DELTA);
114     assertEquals(sf.getValue(Gff3Helper.ALLELES), "A,T");
115
116     sf = geneFeatures.get(2);
117     assertEquals(sf.getFeatureGroup(), "VCF");
118     assertEquals(sf.getBegin(), 4);
119     assertEquals(sf.getEnd(), 4);
120     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
121     assertEquals(sf.getScore(), 2.0e-03, DELTA);
122     assertEquals(sf.getValue(Gff3Helper.ALLELES), "G,C");
123
124     sf = geneFeatures.get(3);
125     assertEquals(sf.getFeatureGroup(), "VCF");
126     assertEquals(sf.getBegin(), 4);
127     assertEquals(sf.getEnd(), 4);
128     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
129     assertEquals(sf.getScore(), 3.0e-03, DELTA);
130     assertEquals(sf.getValue(Gff3Helper.ALLELES), "G,GA");
131
132     /*
133      * verify variant feature(s) added to transcript
134      */
135     List<SequenceFeature> transcriptFeatures = al.getSequenceAt(1)
136             .getSequenceFeatures();
137     assertEquals(transcriptFeatures.size(), 2);
138     sf = transcriptFeatures.get(0);
139     assertEquals(sf.getFeatureGroup(), "VCF");
140     assertEquals(sf.getBegin(), 2);
141     assertEquals(sf.getEnd(), 2);
142     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
143     assertEquals(sf.getScore(), 2.0e-03, DELTA);
144     assertEquals(sf.getValue(Gff3Helper.ALLELES), "G,C");
145     sf = transcriptFeatures.get(1);
146     assertEquals(sf.getFeatureGroup(), "VCF");
147     assertEquals(sf.getBegin(), 2);
148     assertEquals(sf.getEnd(), 2);
149     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
150     assertEquals(sf.getScore(), 3.0e-03, DELTA);
151     assertEquals(sf.getValue(Gff3Helper.ALLELES), "G,GA");
152
153     /*
154      * verify SNP variant feature(s) computed and added to protein
155      * first codon AGC varies to ACC giving S/T
156      */
157     DBRefEntry[] dbRefs = al.getSequenceAt(1).getDBRefs();
158     SequenceI peptide = null;
159     for (DBRefEntry dbref : dbRefs)
160     {
161       if (dbref.getMap().getMap().getFromRatio() == 3)
162       {
163         peptide = dbref.getMap().getTo();
164       }
165     }
166     List<SequenceFeature> proteinFeatures = peptide.getSequenceFeatures();
167     assertEquals(proteinFeatures.size(), 1);
168     sf = proteinFeatures.get(0);
169     assertEquals(sf.getFeatureGroup(), "VCF");
170     assertEquals(sf.getBegin(), 1);
171     assertEquals(sf.getEnd(), 1);
172     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
173     assertEquals(sf.getDescription(), "p.Ser1Thr");
174   }
175
176   private File makeVcf() throws IOException
177   {
178     File f = File.createTempFile("Test", ".vcf");
179     f.deleteOnExit();
180     PrintWriter pw = new PrintWriter(f);
181     for (String vcfLine : VCF)
182     {
183       pw.println(vcfLine);
184     }
185     pw.close();
186     return f;
187   }
188
189   /**
190    * Make a simple alignment with one 'gene' and one 'transcript'
191    * 
192    * @return
193    */
194   private AlignmentI buildAlignment()
195   {
196     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(FASTA,
197             DataSourceType.PASTE);
198
199     /*
200      * map gene1 sequence to chromosome (normally done when the sequence is fetched
201      * from Ensembl and transcripts computed)
202      */
203     AlignmentI alignment = af.getViewport().getAlignment();
204     SequenceI gene1 = alignment.findName("gene1");
205     int[] to = new int[] { 45051610, 45051634 };
206     int[] from = new int[] { gene1.getStart(), gene1.getEnd() };
207     gene1.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(from, to,
208             1, 1));
209
210     /*
211      * map 'transcript1' to chromosome via 'gene1'
212      * transcript1/1-18 is gene1/3-10,15-24
213      * which is chromosome 45051612-45051619,45051624-45051633
214      */
215     to = new int[] { 45051612, 45051619, 45051624, 45051633 };
216     SequenceI transcript1 = alignment.findName("transcript1");
217     from = new int[] { transcript1.getStart(), transcript1.getEnd() };
218     transcript1.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(
219             from, to,
220             1, 1));
221
222     /*
223      * map gene2 to chromosome reverse strand
224      */
225     SequenceI gene2 = alignment.findName("gene2");
226     to = new int[] { 45051634, 45051610 };
227     from = new int[] { gene2.getStart(), gene2.getEnd() };
228     gene2.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(from, to,
229             1, 1));
230
231     /*
232      * map 'transcript2' to chromosome via 'gene2'
233      * transcript2/1-18 is gene2/2-11,16-23
234      * which is chromosome 45051633-45051624,45051619-45051612
235      */
236     to = new int[] { 45051633, 45051624, 45051619, 45051612 };
237     SequenceI transcript2 = alignment.findName("transcript2");
238     from = new int[] { transcript2.getStart(), transcript2.getEnd() };
239     transcript2.setGeneLoci("homo_sapiens", "GRCh38", "17", new MapList(
240             from, to,
241             1, 1));
242
243     /*
244      * add a protein product as a DBRef on transcript1
245      */
246     SequenceI peptide1 = new Sequence("ENSP001", "SWRECD");
247     MapList mapList = new MapList(new int[] { 1, 18 }, new int[] { 1, 6 },
248             3, 1);
249     Mapping map = new Mapping(peptide1, mapList);
250     DBRefEntry product = new DBRefEntry("", "", "ENSP001", map);
251     transcript1.addDBRef(product);
252
253     /*
254      * add a protein product as a DBRef on transcript2
255      */
256     SequenceI peptide2 = new Sequence("ENSP002", "VTLSPA");
257     mapList = new MapList(new int[] { 1, 18 }, new int[] { 1, 6 }, 3, 1);
258     map = new Mapping(peptide2, mapList);
259     product = new DBRefEntry("", "", "ENSP002", map);
260     transcript2.addDBRef(product);
261
262     /*
263      * map gene3 to chromosome 
264      */
265     SequenceI gene3 = alignment.findName("gene3");
266     to = new int[] { 45051610, 45051634 };
267     from = new int[] { gene3.getStart(), gene3.getEnd() };
268     gene3.setGeneLoci("homo_sapiens", "GRCh38", "5", new MapList(from, to,
269             1, 1));
270
271     /*
272      * map 'transcript3' to chromosome
273      */
274     SequenceI transcript3 = alignment.findName("transcript3");
275     to = new int[] { 45051612, 45051619, 45051624, 45051633 };
276     from = new int[] { transcript3.getStart(), transcript3.getEnd() };
277     transcript3.setGeneLoci("homo_sapiens", "GRCh38", "5", new MapList(
278             from, to,
279             1, 1));
280
281     /*
282      * map 'transcript4' to chromosome
283      */
284     SequenceI transcript4 = alignment.findName("transcript4");
285     to = new int[] { 45051615, 45051617, 45051619, 45051632, 45051634,
286         45051634 };
287     from = new int[] { transcript4.getStart(), transcript4.getEnd() };
288     transcript4.setGeneLoci("homo_sapiens", "GRCh38", "5", new MapList(
289             from, to,
290             1, 1));
291
292     /*
293      * add a protein product as a DBRef on transcript3
294      */
295     SequenceI peptide3 = new Sequence("ENSP003", "SWRECD");
296     mapList = new MapList(new int[] { 1, 18 }, new int[] { 1, 6 }, 3, 1);
297     map = new Mapping(peptide3, mapList);
298     product = new DBRefEntry("", "", "ENSP003", map);
299     transcript3.addDBRef(product);
300
301     return alignment;
302   }
303
304   /**
305    * Test with 'gene' and 'transcript' mapped to the reverse strand of the
306    * chromosome. The VCF variant positions (in forward coordinates) should get
307    * correctly located on sequence positions.
308    * 
309    * @throws IOException
310    */
311   @Test(groups = "Functional")
312   public void testDoLoad_reverseStrand() throws IOException
313   {
314     AlignmentI al = buildAlignment();
315
316     VCFLoader loader = new VCFLoader(al);
317
318     File f = makeVcf();
319
320     loader.doLoad(f.getPath(), null);
321
322     /*
323      * verify variant feature(s) added to gene2
324      * gene2/1-25 maps to chromosome 45051634- reverse strand
325      */
326     List<SequenceFeature> geneFeatures = al.getSequenceAt(2)
327             .getSequenceFeatures();
328     SequenceFeatures.sortFeatures(geneFeatures, true);
329     assertEquals(geneFeatures.size(), 4);
330
331     /*
332      * variant A/T at 45051611 maps to T/A at gene position 24
333      */
334     SequenceFeature sf = geneFeatures.get(3);
335     assertEquals(sf.getFeatureGroup(), "VCF");
336     assertEquals(sf.getBegin(), 24);
337     assertEquals(sf.getEnd(), 24);
338     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
339     assertEquals(sf.getScore(), 5.0e-03, DELTA);
340     assertEquals(sf.getValue(Gff3Helper.ALLELES), "T,A");
341
342     /*
343      * variant A/C at 45051611 maps to T/G at gene position 24
344      */
345     sf = geneFeatures.get(2);
346     assertEquals(sf.getFeatureGroup(), "VCF");
347     assertEquals(sf.getBegin(), 24);
348     assertEquals(sf.getEnd(), 24);
349     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
350     assertEquals(sf.getScore(), 4.0e-03, DELTA);
351     assertEquals(sf.getValue(Gff3Helper.ALLELES), "T,G");
352
353     /*
354      * variant G/C at 45051613 maps to C/G at gene position 22
355      */
356     sf = geneFeatures.get(1);
357     assertEquals(sf.getFeatureGroup(), "VCF");
358     assertEquals(sf.getBegin(), 22);
359     assertEquals(sf.getEnd(), 22);
360     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
361     assertEquals(sf.getScore(), 2.0e-03, DELTA);
362     assertEquals(sf.getValue(Gff3Helper.ALLELES), "C,G");
363
364     /*
365      * insertion G/GA at 45051613 maps to an insertion at
366      * the preceding position (21) on reverse strand gene
367      * reference: CAAGC -> GCTTG/21-25
368      * genomic variant: CAAGAC (G/GA)
369      * gene variant: GTCTTG (G/GT at 21)
370      */
371     sf = geneFeatures.get(0);
372     assertEquals(sf.getFeatureGroup(), "VCF");
373     assertEquals(sf.getBegin(), 21);
374     assertEquals(sf.getEnd(), 21);
375     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
376     assertEquals(sf.getScore(), 3.0e-03, DELTA);
377     assertEquals(sf.getValue(Gff3Helper.ALLELES), "G,GT");
378
379     /*
380      * verify 2 variant features added to transcript2
381      */
382     List<SequenceFeature> transcriptFeatures = al.getSequenceAt(3)
383             .getSequenceFeatures();
384     assertEquals(transcriptFeatures.size(), 2);
385
386     /*
387      * insertion G/GT at position 21 of gene maps to position 16 of transcript
388      */
389     sf = transcriptFeatures.get(0);
390     assertEquals(sf.getFeatureGroup(), "VCF");
391     assertEquals(sf.getBegin(), 16);
392     assertEquals(sf.getEnd(), 16);
393     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
394     assertEquals(sf.getScore(), 3.0e-03, DELTA);
395     assertEquals(sf.getValue(Gff3Helper.ALLELES), "G,GT");
396
397     /*
398      * SNP C/G at position 22 of gene maps to position 17 of transcript
399      */
400     sf = transcriptFeatures.get(1);
401     assertEquals(sf.getFeatureGroup(), "VCF");
402     assertEquals(sf.getBegin(), 17);
403     assertEquals(sf.getEnd(), 17);
404     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
405     assertEquals(sf.getScore(), 2.0e-03, DELTA);
406     assertEquals(sf.getValue(Gff3Helper.ALLELES), "C,G");
407
408     /*
409      * verify variant feature(s) computed and added to protein
410      * last codon GCT varies to GGT giving A/G in the last peptide position
411      */
412     DBRefEntry[] dbRefs = al.getSequenceAt(3).getDBRefs();
413     SequenceI peptide = null;
414     for (DBRefEntry dbref : dbRefs)
415     {
416       if (dbref.getMap().getMap().getFromRatio() == 3)
417       {
418         peptide = dbref.getMap().getTo();
419       }
420     }
421     List<SequenceFeature> proteinFeatures = peptide.getSequenceFeatures();
422     assertEquals(proteinFeatures.size(), 1);
423     sf = proteinFeatures.get(0);
424     assertEquals(sf.getFeatureGroup(), "VCF");
425     assertEquals(sf.getBegin(), 6);
426     assertEquals(sf.getEnd(), 6);
427     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
428     assertEquals(sf.getDescription(), "p.Ala6Gly");
429   }
430
431   /**
432    * Tests that if VEP consequence (CSQ) data is present in the VCF data, then
433    * it is added to the variant feature, but restricted where possible to the
434    * consequences for a specific transcript
435    * 
436    * @throws IOException
437    */
438   @Test(groups = "Functional")
439   public void testDoLoad_vepCsq() throws IOException
440   {
441     AlignmentI al = buildAlignment();
442
443     VCFLoader loader = new VCFLoader(al);
444
445     /*
446      * VCF data file with variants at gene3 positions
447      * 1 C/A
448      * 5 C/T
449      * 9 CGT/C (deletion)
450      * 13 C/G, C/T
451      * 17 A/AC (insertion), A/G
452      */
453     loader.doLoad("test/jalview/io/vcf/testVcf.dat", null);
454
455     /*
456      * verify variant feature(s) added to gene3
457      */
458     List<SequenceFeature> geneFeatures = al.findName("gene3")
459             .getSequenceFeatures();
460     SequenceFeatures.sortFeatures(geneFeatures, true);
461     assertEquals(geneFeatures.size(), 7);
462     SequenceFeature sf = geneFeatures.get(0);
463     assertEquals(sf.getBegin(), 1);
464     assertEquals(sf.getEnd(), 1);
465     assertEquals(sf.getScore(), 0.1f, DELTA);
466     assertEquals(sf.getValue("alleles"), "C,A");
467     // gene features include Consequence for all transcripts
468     Map map = (Map) sf.getValue("CSQ");
469     assertEquals(map.size(), 9);
470
471     sf = geneFeatures.get(1);
472     assertEquals(sf.getBegin(), 5);
473     assertEquals(sf.getEnd(), 5);
474     assertEquals(sf.getScore(), 0.2f, DELTA);
475     assertEquals(sf.getValue("alleles"), "C,T");
476     map = (Map) sf.getValue("CSQ");
477     assertEquals(map.size(), 9);
478
479     sf = geneFeatures.get(2);
480     assertEquals(sf.getBegin(), 9);
481     assertEquals(sf.getEnd(), 11); // deletion over 3 positions
482     assertEquals(sf.getScore(), 0.3f, DELTA);
483     assertEquals(sf.getValue("alleles"), "CGG,C");
484     map = (Map) sf.getValue("CSQ");
485     assertEquals(map.size(), 9);
486
487     sf = geneFeatures.get(3);
488     assertEquals(sf.getBegin(), 13);
489     assertEquals(sf.getEnd(), 13);
490     assertEquals(sf.getScore(), 0.5f, DELTA);
491     assertEquals(sf.getValue("alleles"), "C,T");
492     map = (Map) sf.getValue("CSQ");
493     assertEquals(map.size(), 9);
494
495     sf = geneFeatures.get(4);
496     assertEquals(sf.getBegin(), 13);
497     assertEquals(sf.getEnd(), 13);
498     assertEquals(sf.getScore(), 0.4f, DELTA);
499     assertEquals(sf.getValue("alleles"), "C,G");
500     map = (Map) sf.getValue("CSQ");
501     assertEquals(map.size(), 9);
502
503     sf = geneFeatures.get(5);
504     assertEquals(sf.getBegin(), 17);
505     assertEquals(sf.getEnd(), 17);
506     assertEquals(sf.getScore(), 0.7f, DELTA);
507     assertEquals(sf.getValue("alleles"), "A,G");
508     map = (Map) sf.getValue("CSQ");
509     assertEquals(map.size(), 9);
510
511     sf = geneFeatures.get(6);
512     assertEquals(sf.getBegin(), 17);
513     assertEquals(sf.getEnd(), 17); // insertion
514     assertEquals(sf.getScore(), 0.6f, DELTA);
515     assertEquals(sf.getValue("alleles"), "A,AC");
516     map = (Map) sf.getValue("CSQ");
517     assertEquals(map.size(), 9);
518
519     /*
520      * verify variant feature(s) added to transcript3
521      * at columns 5 (1), 17 (2), positions 3, 11
522      * note the deletion at columns 9-11 is not transferred since col 11
523      * has no mapping to transcript 3 
524      */
525     List<SequenceFeature> transcriptFeatures = al.findName("transcript3")
526             .getSequenceFeatures();
527     SequenceFeatures.sortFeatures(transcriptFeatures, true);
528     assertEquals(transcriptFeatures.size(), 3);
529     sf = transcriptFeatures.get(0);
530     assertEquals(sf.getBegin(), 3);
531     assertEquals(sf.getEnd(), 3);
532     assertEquals(sf.getScore(), 0.2f, DELTA);
533     assertEquals(sf.getValue("alleles"), "C,T");
534     // transcript features only have Consequence for that transcripts
535     map = (Map) sf.getValue("CSQ");
536     assertEquals(map.size(), 9);
537     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript3");
538
539     sf = transcriptFeatures.get(1);
540     assertEquals(sf.getBegin(), 11);
541     assertEquals(sf.getEnd(), 11);
542     assertEquals(sf.getScore(), 0.7f, DELTA);
543     assertEquals(sf.getValue("alleles"), "A,G");
544     assertEquals(map.size(), 9);
545     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript3");
546
547     sf = transcriptFeatures.get(2);
548     assertEquals(sf.getBegin(), 11);
549     assertEquals(sf.getEnd(), 11);
550     assertEquals(sf.getScore(), 0.6f, DELTA);
551     assertEquals(sf.getValue("alleles"), "A,AC");
552     assertEquals(map.size(), 9);
553     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript3");
554
555     /*
556      * verify variants computed on protein product for transcript3
557      * peptide is SWRECD
558      * codon variants are AGC/AGT position 1 which is synonymous
559      * and GAG/GGG which is E/G in position 4
560      * the insertion variant is not transferred to the peptide
561      */
562     DBRefEntry[] dbRefs = al.findName("transcript3").getDBRefs();
563     SequenceI peptide = null;
564     for (DBRefEntry dbref : dbRefs)
565     {
566       if (dbref.getMap().getMap().getFromRatio() == 3)
567       {
568         peptide = dbref.getMap().getTo();
569       }
570     }
571     List<SequenceFeature> proteinFeatures = peptide.getSequenceFeatures();
572     assertEquals(proteinFeatures.size(), 1);
573     sf = proteinFeatures.get(0);
574     assertEquals(sf.getFeatureGroup(), "VCF");
575     assertEquals(sf.getBegin(), 4);
576     assertEquals(sf.getEnd(), 4);
577     assertEquals(sf.getType(), SequenceOntologyI.SEQUENCE_VARIANT);
578     assertEquals(sf.getDescription(), "p.Glu4Gly");
579
580     /*
581      * verify variant feature(s) added to transcript4
582      * at columns 13 (2) and 17 (2), positions 7 and 11
583      */
584     transcriptFeatures = al.findName("transcript4").getSequenceFeatures();
585     SequenceFeatures.sortFeatures(transcriptFeatures, true);
586     assertEquals(transcriptFeatures.size(), 4);
587     sf = transcriptFeatures.get(0);
588     assertEquals(sf.getBegin(), 7);
589     assertEquals(sf.getEnd(), 7);
590     assertEquals(sf.getScore(), 0.5f, DELTA);
591     assertEquals(sf.getValue("alleles"), "C,T");
592     assertEquals(map.size(), 9);
593     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript4");
594
595     sf = transcriptFeatures.get(1);
596     assertEquals(sf.getBegin(), 7);
597     assertEquals(sf.getEnd(), 7);
598     assertEquals(sf.getScore(), 0.4f, DELTA);
599     assertEquals(sf.getValue("alleles"), "C,G");
600     assertEquals(map.size(), 9);
601     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript4");
602
603     sf = transcriptFeatures.get(2);
604     assertEquals(sf.getBegin(), 11);
605     assertEquals(sf.getEnd(), 11);
606     assertEquals(sf.getScore(), 0.7f, DELTA);
607     assertEquals(sf.getValue("alleles"), "A,G");
608     assertEquals(map.size(), 9);
609     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript4");
610
611     sf = transcriptFeatures.get(3);
612     assertEquals(sf.getBegin(), 11);
613     assertEquals(sf.getEnd(), 11);
614     assertEquals(sf.getScore(), 0.6f, DELTA);
615     assertEquals(sf.getValue("alleles"), "A,AC");
616     assertEquals(map.size(), 9);
617     assertEquals(sf.getValueAsString("CSQ", "Feature"), "transcript4");
618   }
619 }