package org.molgenis.data.annotation.core.entity.impl.gavin; import org.molgenis.data.DataService; import org.molgenis.data.Entity; import org.molgenis.data.annotation.core.RepositoryAnnotator; import org.molgenis.data.annotation.core.effects.EffectsMetaData; import org.molgenis.data.annotation.core.entity.AnnotatorConfig; import org.molgenis.data.annotation.core.entity.impl.CaddAnnotator; import org.molgenis.data.annotation.core.entity.impl.ExacAnnotator; import org.molgenis.data.annotation.core.query.GeneNameQueryCreator; import org.molgenis.data.annotation.core.resources.Resources; import org.molgenis.data.annotation.core.resources.impl.ResourcesImpl; import org.molgenis.data.annotation.web.AnnotationService; import org.molgenis.data.annotation.web.settings.GavinAnnotatorSettings; import org.molgenis.data.listeners.EntityListenersService; import org.molgenis.data.meta.EntityTypeDependencyResolver; import org.molgenis.data.meta.model.Attribute; import org.molgenis.data.meta.model.AttributeFactory; import org.molgenis.data.meta.model.EntityType; import org.molgenis.data.meta.model.EntityTypeFactory; import org.molgenis.data.support.DynamicEntity; import org.molgenis.data.vcf.model.VcfAttributes; import org.molgenis.data.vcf.utils.VcfWriterUtils; import org.molgenis.test.data.AbstractMolgenisSpringTest; import org.molgenis.util.GenericDependencyResolver; import org.molgenis.util.ResourceUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import static java.util.Collections.singletonList; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.molgenis.data.annotation.core.entity.impl.gavin.GavinAnnotator.*; import static org.molgenis.data.meta.AttributeType.STRING; import static org.molgenis.data.meta.AttributeType.XREF; import static org.testng.Assert.*; @ContextConfiguration(classes = { GavinAnnotatorTest.Config.class, GavinAnnotator.class }) public class GavinAnnotatorTest extends AbstractMolgenisSpringTest { private static final String BENIGN = "Benign"; private static final String CALIBRATED = "calibrated"; @Autowired ApplicationContext context; @Autowired AttributeFactory attributeFactory; @Autowired EntityTypeFactory entityTypeFactory; @Autowired VcfAttributes vcfAttributes; @Autowired RepositoryAnnotator annotator; @Autowired EffectsMetaData effectsMetaData; private EntityType emd; private EntityType entityType; @BeforeClass public void beforeClass() throws IOException { AnnotatorConfig annotatorConfig = context.getBean(AnnotatorConfig.class); annotatorConfig.init(); emd = entityTypeFactory.create().setName("gavin"); entityType = entityTypeFactory.create().setName("test_variant"); List<Attribute> refAttributesList = Arrays.asList(CaddAnnotator.createCaddScaledAttr(attributeFactory), ExacAnnotator.getExacAFAttr(attributeFactory), vcfAttributes.getAltAttribute()); entityType.addAttributes(refAttributesList); Attribute refAttr = attributeFactory.create().setName("test_variant").setDataType(XREF).setRefEntity(entityType) .setDescription("This annotator needs a references to an entity containing: " + StreamSupport .stream(refAttributesList.spliterator(), false).map(Attribute::getName) .collect(Collectors.joining(", "))); emd.addAttributes(Arrays.asList(refAttr, vcfAttributes.getAltAttribute())); Attribute idAttr = attributeFactory.create().setName("idAttribute").setAuto(true).setIdAttribute(true); emd.addAttribute(idAttr); emd.addAttributes(effectsMetaData.getOrderedAttributes()); emd.addAttribute(attributeFactory.create().setName(EffectsMetaData.VARIANT).setNillable(false).setDataType(XREF) .setRefEntity(entityType)); Attribute classification = attributeFactory.create().setName(CLASSIFICATION).setDataType(STRING) .setDescription(CLASSIFICATION).setLabel(CLASSIFICATION); Attribute confidence = attributeFactory.create().setName(CONFIDENCE).setDataType(STRING) .setDescription(CONFIDENCE).setLabel(CONFIDENCE); Attribute reason = attributeFactory.create().setName(REASON).setDataType(STRING).setDescription(REASON) .setLabel(REASON); emd.addAttributes(Arrays.asList(classification, confidence, reason)); entityType.addAttribute(idAttr); } @Test public void testGeneWithNullFields() { Entity variantEntity = getVariantEntity("A,T", "6,80", "0.00001,0.00001"); Entity effectEntity = getEffectEntity("T", "HIGH", "ABCD1", variantEntity); Iterator<Entity> results = annotator.annotate(singletonList(effectEntity)); assertTrue(results.hasNext()); Entity resultEntity = results.next(); assertFalse(results.hasNext()); assertEquals(resultEntity.get(CLASSIFICATION), BENIGN); assertEquals(resultEntity.get(CONFIDENCE), CALIBRATED); assertEquals(resultEntity.get(REASON), "Variant MAF of 1.0E-5 is greater than 0.0."); } @Test public void testAnnotateHighMafBenign() { Entity variant_entity = getVariantEntity("A,T", "1,2", "2,3"); Entity effect_entity = getEffectEntity("A", "HIGH", null, variant_entity); Iterator<Entity> results = annotator.annotate(singletonList(effect_entity)); assertTrue(results.hasNext()); Entity resultEntity = results.next(); assertFalse(results.hasNext()); assertEquals(resultEntity.get(CLASSIFICATION), "Benign"); assertEquals(resultEntity.get(CONFIDENCE), "genomewide"); assertEquals(resultEntity.get(REASON), "Variant MAF of 2.0 is not rare enough to generally be considered pathogenic."); } @Test public void testAnnotateLowCaddBenign() { Entity variant_entity = getVariantEntity("A,T", "1,2", "0.00001,0.00001"); Entity effect_entity = getEffectEntity("A", "HIGH", null, variant_entity); Iterator<Entity> results = annotator.annotate(singletonList(effect_entity)); assertTrue(results.hasNext()); Entity resultEntity = results.next(); assertFalse(results.hasNext()); assertEquals(resultEntity.get(CLASSIFICATION), "Benign"); assertEquals(resultEntity.get(CONFIDENCE), "genomewide"); assertEquals(resultEntity.get(REASON), "Variant CADD score of 1.0 is less than a global threshold of 15, although the variant MAF of 1.0E-5 is rare enough to be potentially pathogenic."); } @Test public void testAnnotateNoCaddVOUS() { Entity variant_entity = getVariantEntity("A,T", null, "0.00001,0.00001"); Entity effect_entity = getEffectEntity("A", "HIGH", "TFR2", variant_entity); Iterator<Entity> results = annotator.annotate(singletonList(effect_entity)); assertTrue(results.hasNext()); Entity resultEntity = results.next(); assertFalse(results.hasNext()); assertEquals(resultEntity.get(CLASSIFICATION), "VOUS"); assertEquals(resultEntity.get(CONFIDENCE), "genomewide"); assertEquals(resultEntity.get(REASON), "Unable to classify variant as benign or pathogenic. The combination of HIGH impact, a CADD score of null and MAF of 1.0E-5 in TFR2 is inconclusive."); } @Test public void testAnnotateLowVariantCaddBenign() { Entity variant_entity = getVariantEntity("A,T", "6,80", "0.00001,0.00001"); Entity effect_entity = getEffectEntity("A", "HIGH", "TFR2", variant_entity); Iterator<Entity> results = annotator.annotate(singletonList(effect_entity)); assertTrue(results.hasNext()); Entity resultEntity = results.next(); assertFalse(results.hasNext()); assertEquals(resultEntity.get(CLASSIFICATION), "Benign"); assertEquals(resultEntity.get(CONFIDENCE), "calibrated"); assertEquals(resultEntity.get(REASON), "Variant CADD score of 6.0 is less than 13.329999999999998 for this gene."); } @Test public void testAnnotateHighCaddPathogenic() { Entity variant_entity = getVariantEntity("A,T", "6,80", "0.00001,0.00001"); Entity effect_entity = getEffectEntity("T", "HIGH", "TFR2", variant_entity); Iterator<Entity> results = annotator.annotate(singletonList(effect_entity)); assertTrue(results.hasNext()); Entity resultEntity = results.next(); assertFalse(results.hasNext()); assertEquals(resultEntity.get(CLASSIFICATION), "Pathogenic"); assertEquals(resultEntity.get(CONFIDENCE), "calibrated"); assertEquals(resultEntity.get(REASON), "Variant CADD score of 80.0 is greater than 30.35 for this gene."); } private Entity getEffectEntity(String alt, String putativeImpact, String geneName, Entity variantEntity) { Entity effectEntity = new DynamicEntity(emd); effectEntity.set(EffectsMetaData.ALT, alt); effectEntity.set(EffectsMetaData.PUTATIVE_IMPACT, putativeImpact); effectEntity.set(EffectsMetaData.GENE_NAME, geneName); effectEntity.set(VcfWriterUtils.VARIANT, variantEntity); return effectEntity; } private Entity getVariantEntity(String alt, String caddScaled, String exacAF) { Entity variantEntity = new DynamicEntity(entityType); variantEntity.set(VcfAttributes.ALT, alt); variantEntity.set(CaddAnnotator.CADD_SCALED, caddScaled); variantEntity.set(ExacAnnotator.EXAC_AF, exacAF); return variantEntity; } @Configuration @ComponentScan({ "org.molgenis.data.vcf.model", "org.molgenis.data.annotation.core.effects" }) public static class Config { @Bean public GavinAnnotatorSettings gavinAnnotatorSettings() { GavinAnnotatorSettings settings = mock(GavinAnnotatorSettings.class); when(settings.getString(GavinAnnotatorSettings.Meta.VARIANT_FILE_LOCATION)) .thenReturn(ResourceUtils.getFile(getClass(), "/gavin/GAVIN_calibrations_r0.1.xlsx").getPath()); return settings; } @Bean public DataService dataService() { return mock(DataService.class); } @Bean public AnnotationService annotationService() { return mock(AnnotationService.class); } @Bean public Resources resources() { return new ResourcesImpl(); } @Bean public Entity caddAnnotatorSettings() { return mock(Entity.class); } @Bean public Entity exacAnnotatorSettings() { return mock(Entity.class); } @Bean public GeneNameQueryCreator geneNameQueryCreator() { return new GeneNameQueryCreator(); } @Bean public EntityListenersService entityListenersService() { return new EntityListenersService(); } @Bean public EntityTypeDependencyResolver entityTypeDependencyResolver() { return new EntityTypeDependencyResolver(genericDependencyResolver()); } @Bean public GenericDependencyResolver genericDependencyResolver() { return new GenericDependencyResolver(); } } }