From 9f62e4d4ba429577699ba7480c616a6fa44c8326 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Mon, 2 Sep 2024 11:32:58 +0200 Subject: [PATCH 01/28] WIP --- .../matcher/AppCommandLineOptions.java | 8 ++++ .../matcher/AppCommandLineRunner.java | 10 ++++- .../vcf/inheritance/matcher/Genotype.java | 13 ++++++ .../matcher/InheritanceService.java | 2 +- .../matcher/PedigreeInheritanceChecker.java | 1 + .../vcf/inheritance/matcher/VcfReader.java | 40 +++++++++++++++++++ .../inheritance/matcher/VcfReaderFactory.java | 7 ++++ .../matcher/VcfReaderFactoryImpl.java | 14 +++++++ .../vcf/inheritance/matcher/VcfRecord.java | 17 ++++++++ .../vcf/inheritance/matcher/VepMapper.java | 19 +++++++++ .../inheritance/matcher/model/Settings.java | 1 + src/test/resources/integration.vcf | 13 ------ 12 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java index 017f2ec..bb3e951 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java @@ -24,6 +24,8 @@ class AppCommandLineOptions { static final String OPT_DEBUG_LONG = "debug"; static final String OPT_VERSION = "v"; static final String OPT_VERSION_LONG = "version"; + static final String OPT_CLASSES = "pc"; + static final String OPT_CLASSES_LONG = "pathogenicClasses"; private static final Options APP_OPTIONS; private static final Options APP_VERSION_OPTIONS; @@ -54,6 +56,12 @@ class AppCommandLineOptions { .longOpt(OPT_PROBANDS_LONG) .desc("Comma-separated list of proband sample identifiers.") .build()); + appOptions.addOption( + Option.builder(OPT_CLASSES) + .hasArg(true) + .longOpt(OPT_CLASSES_LONG) + .desc("Comma-separated list of classes to be treated as pathogenic in the inheritance matcher") + .build()); appOptions.addOption( Option.builder(OPT_FORCE) .longOpt(OPT_FORCE_LONG) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java index e9e0a8c..417be26 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java @@ -96,6 +96,13 @@ private Settings mapSettings(CommandLine commandLine) { probandNames = List.of(); } + List pathogenicClasses; + if (commandLine.hasOption(OPT_CLASSES)) { + pathogenicClasses = Arrays.asList(commandLine.getOptionValue(OPT_CLASSES).split(",")); + } else { + pathogenicClasses = List.of(); + } + List pedPaths; if (commandLine.hasOption(OPT_PED)) { pedPaths = parsePaths(commandLine.getOptionValue(OPT_PED)); @@ -108,7 +115,8 @@ private Settings mapSettings(CommandLine commandLine) { boolean debugMode = commandLine.hasOption(OPT_DEBUG); return Settings.builder().inputVcfPath(inputPath).inputPedPaths(pedPaths) - .outputPath(outputPath).probands(probandNames).overwrite(overwriteOutput).debug(debugMode) + .outputPath(outputPath).probands(probandNames).overwrite(overwriteOutput). + pathogenicClasses(pathogenicClasses).debug(debugMode) .build(); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java new file mode 100644 index 0000000..6cc2e4e --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java @@ -0,0 +1,13 @@ +package org.molgenis.vcf.inheritance.matcher; + +import static java.util.Objects.requireNonNull; + +public class Genotype { + htsjdk.variant.variantcontext.Genotype genotype; + + public Genotype(htsjdk.variant.variantcontext.Genotype genotype) { + this.genotype = requireNonNull(genotype); + } + + //TODO: implement functions to treat benign as REF en pathogenic as ALT +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index f7286a1..e4e97f4 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -64,7 +64,7 @@ public void run(Settings settings) { vcfFileReader.forEach(variantContextList::add); Map> geneVariantMap = createGeneVariantMap(vepMapper, knownGenes, variantContextList); - variantContextList.stream().filter(vc -> vc.getAlternateAlleles().size() == 1).map( + variantContextList.stream().filter(vc -> vc.getAlternateAlleles().size() > 1).map( vc -> processSingleVariantcontext(probands, vepMapper, familyList, geneVariantMap, vc)).forEach(writer::add); } catch (IOException ioException) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java index a9e9013..6f0c4f3 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java @@ -37,6 +37,7 @@ public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, this.deNovoChecker = deNovoChecker; } + //TODO replace geneVariantMap with context incl pathogenic classes Inheritance calculatePedigreeInheritance( Map> geneVariantMap, VariantContext variantContext, Sample sample, Pedigree filteredFamily, ArCompoundChecker arCompoundChecker) { Inheritance inheritance = Inheritance.builder().build(); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java new file mode 100644 index 0000000..2114f86 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java @@ -0,0 +1,40 @@ +package org.molgenis.vcf.inheritance.matcher; + +import static java.util.Objects.requireNonNull; + +import htsjdk.variant.vcf.VCFFileReader; + +import java.util.Set; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * {@link VCFFileReader} wrapper that works with nested metadata and data (e.g. CSQ INFO fields). + */ +public class VcfReader implements AutoCloseable { + + private final VCFFileReader vcfFileReader; + + public VcfReader(VCFFileReader vcfFileReader) { + this.vcfFileReader = requireNonNull(vcfFileReader); + } + + public Stream stream() { + return StreamSupport.stream(vcfFileReader.spliterator(), false).map(VcfRecord::new); + } + + public Stream filteredStream(Set classes) { + //FIXME: filter on classes + return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(VcfRecord::new); + } + + public Stream filteredStream(Set classes, String geneId) { + //FIXME: filter on classes and geneId + return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(VcfRecord::new); + } + + @Override + public void close() { + vcfFileReader.close(); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java new file mode 100644 index 0000000..3d47257 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java @@ -0,0 +1,7 @@ +package org.molgenis.vcf.inheritance.matcher; + +import org.molgenis.vcf.inheritance.matcher.model.Settings; + +public interface VcfReaderFactory { + VcfReader create(Settings settings); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java new file mode 100644 index 0000000..95b13cd --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java @@ -0,0 +1,14 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.vcf.VCFFileReader; +import org.molgenis.vcf.inheritance.matcher.model.Settings; + +import java.nio.file.Path; + +public class VcfReaderFactoryImpl implements VcfReaderFactory{ + @Override + public VcfReader create(Settings settings) { + Path inputVcfPath = settings.getInputVcfPath(); + return new VcfReader(new VCFFileReader(inputVcfPath.toFile(), false)); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java new file mode 100644 index 0000000..4eeecf7 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java @@ -0,0 +1,17 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.VariantContext; + +import static java.util.Objects.requireNonNull; + +public class VcfRecord { + VariantContext variantContext; + + public VcfRecord(VariantContext variantContext) { + this.variantContext = requireNonNull(variantContext); + } + + public Genotype getGenotype(String sampleId){ + return new Genotype(variantContext.getGenotype(sampleId)); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java index 832f833..a607d8b 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java @@ -21,6 +21,8 @@ public class VepMapper { public static final String GENE = "Gene"; + public static final String ALLELE_NUM = "ALLELE_NUM"; + public static final String VIP_CLASS = "VIPC"; public static final String SYMBOL_SOURCE = "SYMBOL_SOURCE"; private static final String INFO_DESCRIPTION_PREFIX = "Consequence annotations from Ensembl VEP. Format: "; @@ -30,6 +32,8 @@ public class VepMapper { private int geneIndex = -1; private int geneSourceIndex = -1; private int inheritanceIndex = -1; + private int alleleNumIndex = -1; + private int classIndex = -1; public VepMapper(VCFFileReader vcfFileReader, FieldMetadataService fieldMetadataService) { this.fieldMetadataService = fieldMetadataService; @@ -53,6 +57,8 @@ private void init(VCFFileReader vcfFileReader) { geneIndex = nestedFields.get(GENE) != null ? nestedFields.get(GENE).getIndex():-1; geneSourceIndex = nestedFields.get(SYMBOL_SOURCE) != null ? nestedFields.get(SYMBOL_SOURCE).getIndex():-1; inheritanceIndex = nestedFields.get(INHERITANCE) != null ? nestedFields.get(INHERITANCE).getIndex():-1; + alleleNumIndex = nestedFields.get(ALLELE_NUM) != null ? nestedFields.get(ALLELE_NUM).getIndex():-1; + classIndex = nestedFields.get(VIP_CLASS) != null ? nestedFields.get(VIP_CLASS).getIndex():-1; return; } } @@ -92,6 +98,19 @@ public VariantContextGenes getGenes(VariantContext vc, Map knownGe return genesBuilder.build(); } + public Set getClassesForAllele(VariantContext vc, int alleleIndex){ + List vepValues = vc.getAttributeAsStringList(vepFieldId, ""); + Set classes = new HashSet<>(); + for (String vepValue : vepValues) { + String[] vepSplit = vepValue.split("\\|", -1); + int csqAlleleIndex = Integer.parseInt(vepSplit[alleleNumIndex]); + if(csqAlleleIndex == alleleIndex){ + classes.add(vepSplit[classIndex]); + } + } + return classes; + } + private void mapGeneInheritance(Set modes, String[] inheritanceModes) { for (String mode : inheritanceModes) { switch (mode) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java index 1725a3f..84610cc 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java @@ -13,6 +13,7 @@ public class Settings { List inputPedPaths; Path outputPath; List probands; + List pathogenicClasses; boolean overwrite; boolean debug; boolean strict; diff --git a/src/test/resources/integration.vcf b/src/test/resources/integration.vcf index ea52846..fd01193 100644 --- a/src/test/resources/integration.vcf +++ b/src/test/resources/integration.vcf @@ -36,17 +36,4 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 -1 123460 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -1 123461 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|1|AD GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 -2 1 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 -3 2 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 -4 123457 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5||XLR,G|GENE7|EntrezGene|ID7||XLD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6||XLR GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 From 7b335815e6d82ec209f0dbc5e7ecced602bf1c96 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 4 Sep 2024 10:46:30 +0200 Subject: [PATCH 02/28] Refactor inheritance matcher to use VcfRecord --- .../vcf/inheritance/matcher/Annotator.java | 24 +-- .../matcher/AppCommandLineRunner.java | 22 +-- .../vcf/inheritance/matcher/AppRunner.java | 6 + .../inheritance/matcher/AppRunnerFactory.java | 9 + .../matcher/AppRunnerFactoryImpl.java | 52 ++++++ .../inheritance/matcher/AppRunnerImpl.java | 41 +++++ .../vcf/inheritance/matcher/Genotype.java | 86 ++++++++- .../matcher/InheritanceService.java | 114 +++++------- .../matcher/PedigreeInheritanceChecker.java | 52 +++--- .../vcf/inheritance/matcher/RecordWriter.java | 11 ++ .../matcher/RecordWriterFactory.java | 7 + .../matcher/RecordWriterFactoryImpl.java | 42 +++++ .../inheritance/matcher/RecordWriterImpl.java | 31 ++++ .../matcher/VariantContextUtils.java | 16 +- .../vcf/inheritance/matcher/VcfReader.java | 30 ++- .../matcher/VcfReaderFactoryImpl.java | 14 +- .../vcf/inheritance/matcher/VcfRecord.java | 37 +++- .../vcf/inheritance/matcher/VepMapper.java | 28 +-- .../matcher/checker/AdChecker.java | 22 +-- .../checker/AdNonPenetranceChecker.java | 17 +- .../matcher/checker/ArChecker.java | 19 +- .../matcher/checker/ArCompoundChecker.java | 69 ++++--- .../matcher/checker/DeNovoChecker.java | 55 +++--- .../matcher/checker/HaploidChecker.java | 13 +- .../matcher/checker/InheritanceChecker.java | 8 +- .../matcher/checker/MtChecker.java | 7 +- .../matcher/checker/XlChecker.java | 12 +- .../matcher/checker/XldChecker.java | 15 +- .../matcher/checker/XlrChecker.java | 19 +- .../matcher/checker/YlChecker.java | 12 +- .../matcher/model/CompoundCheckResult.java | 3 +- .../inheritance/matcher/model/Settings.java | 5 +- .../util/InheritanceServiceFactory.java | 4 +- .../util/InheritanceServiceFactoryImpl.java | 13 +- .../matcher/util/InheritanceUtils.java | 7 - .../inheritance/matcher/AnnotatorTest.java | 9 +- .../vcf/inheritance/matcher/AppIT.java | 4 +- .../PedigreeInheritanceCheckerTest.java | 173 +++++++++--------- .../matcher/VariantContextUtilsTest.java | 2 +- .../inheritance/matcher/VepMapperTest.java | 14 +- .../matcher/checker/AdCheckerTest.java | 7 +- .../matcher/checker/AdNonPenCheckerTest.java | 11 +- .../matcher/checker/ArCheckerTest.java | 7 +- .../checker/ArCompoundCheckerTest.java | 7 +- .../matcher/checker/DeNovoCheckerTest.java | 7 +- .../matcher/checker/MtCheckerTest.java | 5 +- .../matcher/checker/XldCheckerTest.java | 7 +- .../matcher/checker/XlrCheckerTest.java | 7 +- .../matcher/checker/YlCheckerTest.java | 5 +- .../InheritanceServiceFactoryImplTest.java | 15 +- .../matcher/util/VariantContextTestUtil.java | 9 +- src/test/resources/integration.vcf | 13 ++ 52 files changed, 780 insertions(+), 444 deletions(-) create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunner.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactory.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 3f2ead5..32670b2 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -15,11 +15,9 @@ import htsjdk.variant.vcf.VCFHeaderLine; import htsjdk.variant.vcf.VCFHeaderLineCount; import htsjdk.variant.vcf.VCFHeaderLineType; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Map; + +import java.util.*; import java.util.Map.Entry; -import java.util.Set; import java.util.stream.Collectors; import org.molgenis.vcf.inheritance.matcher.model.*; @@ -70,26 +68,28 @@ VCFHeader annotateHeader(VCFHeader vcfHeader) { return vcfHeader; } - VariantContext annotateInheritance(VariantContext vc, Map familyMap, + VcfRecord annotateInheritance(VcfRecord vcfRecord, Map familyMap, Map annotationMap) { - GenotypesContext genotypesContext = GenotypesContext.copy(vc.getGenotypes()); - VariantContextBuilder variantContextBuilder = new VariantContextBuilder(vc); + //FIXME + GenotypesContext genotypesContext = GenotypesContext.copy(vcfRecord.unwrap().getGenotypes()); + VariantContextBuilder variantContextBuilder = new VariantContextBuilder(vcfRecord.unwrap()); for (Entry sampleFamilyEntry : familyMap.entrySet()) { for (Sample sample : sampleFamilyEntry.getValue().getMembers().values()) { String sampleId = sample.getPerson().getIndividualId(); if (annotationMap.containsKey(sampleId)) { - annotateGenotype(vc, annotationMap.get(sampleId), genotypesContext, sample); + annotateGenotype(vcfRecord, annotationMap.get(sampleId), genotypesContext, sample); } } } - return variantContextBuilder.genotypes(genotypesContext).make(); + //FIXME + return new VcfRecord(variantContextBuilder.genotypes(genotypesContext).make(), Collections.emptyList()); } - private void annotateGenotype(VariantContext vc, Annotation annotation, + private void annotateGenotype(VcfRecord vcfRecord, Annotation annotation, GenotypesContext genotypesContext, Sample sample) { - if (vc.getGenotype(sample.getPerson().getIndividualId()) != null) { + if (vcfRecord.getGenotype(sample.getPerson().getIndividualId()) != null) { GenotypeBuilder genotypeBuilder = new GenotypeBuilder( - vc.getGenotype(sample.getPerson().getIndividualId())); + vcfRecord.getGenotype(sample.getPerson().getIndividualId()).unwrap()); String inheritanceModes = String .join(",", mapInheritanceModes(annotation.getInheritance())); if (!inheritanceModes.isEmpty()) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java index 417be26..e7e0ea3 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java @@ -3,7 +3,6 @@ import ch.qos.logback.classic.Level; import org.apache.commons.cli.*; import org.molgenis.vcf.inheritance.matcher.model.Settings; -import org.molgenis.vcf.inheritance.matcher.util.InheritanceServiceFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -14,6 +13,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Set; import static java.util.Objects.requireNonNull; import static org.molgenis.vcf.inheritance.matcher.AppCommandLineOptions.*; @@ -30,15 +30,14 @@ class AppCommandLineRunner implements CommandLineRunner { private final String appName; private final String appVersion; private final CommandLineParser commandLineParser; - private final InheritanceServiceFactory inheritanceServiceFactory; + private final AppRunnerFactoryImpl appRunnerFactoryImpl; AppCommandLineRunner( - @Value("${app.name}") String appName, - @Value("${app.version}") String appVersion, - InheritanceServiceFactory inheritanceServiceFactory) { + @Value("${app.name}") String appName, + @Value("${app.version}") String appVersion, AppRunnerFactoryImpl appRunnerFactoryImpl, App app) { this.appName = requireNonNull(appName); this.appVersion = requireNonNull(appVersion); - this.inheritanceServiceFactory = requireNonNull(inheritanceServiceFactory); + this.appRunnerFactoryImpl = requireNonNull(appRunnerFactoryImpl); this.commandLineParser = new DefaultParser(); } @@ -69,9 +68,8 @@ public void run(String... args) { CommandLine commandLine = getCommandLine(args); org.molgenis.vcf.inheritance.matcher.AppCommandLineOptions.validateCommandLine(commandLine); Settings settings = mapSettings(commandLine); - InheritanceService inheritanceService = inheritanceServiceFactory.create(); - try { - inheritanceService.run(settings); + try(AppRunner appRunner = appRunnerFactoryImpl.create(settings)){ + appRunner.run(); } catch (Exception e) { LOGGER.error(e.getLocalizedMessage(), e); System.exit(STATUS_MISC_ERROR); @@ -96,11 +94,11 @@ private Settings mapSettings(CommandLine commandLine) { probandNames = List.of(); } - List pathogenicClasses; + Set pathogenicClasses; if (commandLine.hasOption(OPT_CLASSES)) { - pathogenicClasses = Arrays.asList(commandLine.getOptionValue(OPT_CLASSES).split(",")); + pathogenicClasses = Set.of(commandLine.getOptionValue(OPT_CLASSES).split(",")); } else { - pathogenicClasses = List.of(); + pathogenicClasses = Set.of(); } List pedPaths; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunner.java new file mode 100644 index 0000000..c388dec --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunner.java @@ -0,0 +1,6 @@ +package org.molgenis.vcf.inheritance.matcher; + +public interface AppRunner extends AutoCloseable { + + void run(); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactory.java new file mode 100644 index 0000000..fcea846 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactory.java @@ -0,0 +1,9 @@ +package org.molgenis.vcf.inheritance.matcher; + + +import org.molgenis.vcf.inheritance.matcher.model.Settings; + +public interface AppRunnerFactory { + + AppRunner create(Settings settings); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java new file mode 100644 index 0000000..7b765b0 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java @@ -0,0 +1,52 @@ +package org.molgenis.vcf.inheritance.matcher; + +import org.molgenis.vcf.inheritance.matcher.model.Settings; +import org.molgenis.vcf.inheritance.matcher.util.InheritanceServiceFactory; +import org.molgenis.vcf.inheritance.matcher.util.VepMetadataServiceFactory; +import org.molgenis.vcf.utils.metadata.FieldMetadataService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import static java.util.Objects.requireNonNull; + +@Component +class AppRunnerFactoryImpl implements AppRunnerFactory { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppRunnerFactoryImpl.class); + + private final VcfReaderFactory vcfReaderFactory; + private final RecordWriterFactory recordWriterFactory; + private final InheritanceServiceFactory inheritanceServiceFactory; + private final VepMetadataServiceFactory vepMetadataServiceFactory; + + AppRunnerFactoryImpl( + VcfReaderFactory vcfReaderFactory, + RecordWriterFactory recordWriterFactory, + InheritanceServiceFactory inheritanceServiceFactory, + VepMetadataServiceFactory vepMetadataServiceFactory) { + this.vcfReaderFactory = requireNonNull(vcfReaderFactory); + this.recordWriterFactory = requireNonNull(recordWriterFactory); + this.inheritanceServiceFactory = inheritanceServiceFactory; + this.vepMetadataServiceFactory = vepMetadataServiceFactory; + } + + // Suppress 'Resources should be closed' + @SuppressWarnings("java:S2095") + @Override + public AppRunner create(Settings settings) { + VcfReader vcfReader = vcfReaderFactory.create(settings); + VepMapper vepMapper = new VepMapper(vcfReader.getFileHeader(), vepMetadataServiceFactory.create()); + try { + RecordWriter recordWriter = recordWriterFactory.create(settings); + return new AppRunnerImpl(vcfReader, recordWriter, inheritanceServiceFactory.create(settings, vepMapper)); + } catch (Exception e) { + try { + vcfReader.close(); + } catch (Exception closeException) { + LOGGER.warn("error closing vcf reader", closeException); + } + throw e; + } + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java new file mode 100644 index 0000000..4e1d13b --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java @@ -0,0 +1,41 @@ +package org.molgenis.vcf.inheritance.matcher; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.util.Objects.requireNonNull; + +class AppRunnerImpl implements AppRunner { + + private static final Logger LOGGER = LoggerFactory.getLogger(AppRunnerImpl.class); + + private final VcfReader vcfReader; + private final RecordWriter recordWriter; + private final InheritanceService inheritanceService; + + AppRunnerImpl(VcfReader vcfReader, RecordWriter recordWriter, InheritanceService inheritanceService) { + this.vcfReader = requireNonNull(vcfReader); + this.recordWriter = requireNonNull(recordWriter); + this.inheritanceService = inheritanceService; + } + + public void run() { + LOGGER.info("Matching inheritance ..."); + inheritanceService.run(vcfReader, recordWriter); + LOGGER.info("done"); + } + + @Override + public void close() { + try { + recordWriter.close(); + } catch (Exception e) { + LOGGER.error("error closing writer", e); + } + try { + vcfReader.close(); + } catch (Exception e) { + LOGGER.error("error closing reader", e); + } + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java index 6cc2e4e..ed9bc81 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java @@ -1,13 +1,95 @@ package org.molgenis.vcf.inheritance.matcher; +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.GenotypeBuilder; +import htsjdk.variant.variantcontext.VariantContext; +import java.util.List; + import static java.util.Objects.requireNonNull; public class Genotype { htsjdk.variant.variantcontext.Genotype genotype; + private final VariantContext variantContext; + private final List pathogenicAlleles; - public Genotype(htsjdk.variant.variantcontext.Genotype genotype) { + public Genotype(htsjdk.variant.variantcontext.Genotype genotype, VariantContext variantContext, List pathogenicAlleles) { this.genotype = requireNonNull(genotype); + this.variantContext = requireNonNull(variantContext); + this.pathogenicAlleles = requireNonNull(pathogenicAlleles); + } + + public htsjdk.variant.variantcontext.Genotype unwrap() { + return genotype; + } + + //Consider Benign allele as a REF allele + //FIXME: private + public htsjdk.variant.variantcontext.Genotype getEffectiveGenotype() { + if (genotype.isNoCall()) { + return genotype; + } + return GenotypeBuilder.create(genotype.getSampleName(), genotype.getAlleles().stream().map(this::mapAllele).toList()); + } + + private Allele mapAllele(Allele allele) { + if(isBenign(allele)){ + return variantContext.getReference(); + } + return allele; + } + + private boolean isBenign(Allele allele) { + return !this.pathogenicAlleles.contains(allele); + } + + public boolean isHomRef() { + //TODO:implement + return genotype.isHomRef(); + } + + public boolean isNoCall() { + //TODO:implement + return genotype.isNoCall(); + } + + public boolean isMixed() { + //TODO:implement + return genotype.isMixed(); + } + + public int getPloidy() { + return genotype.getPloidy(); + } + + public boolean isCalled() { + return genotype.isCalled(); + } + + public boolean isHom() { + return genotype.isHom(); + } + + public boolean hasAltAllele() { + return genotype.hasAltAllele(); + } + + public List getAlleles() { + return genotype.getAlleles(); + } + + public boolean isHet() { + return genotype.isHet(); + } + + public boolean isPhased() { + return genotype.isPhased(); + } + + public boolean isHomAlt() { + return genotype.isHomVar(); } - //TODO: implement functions to treat benign as REF en pathogenic as ALT + public Allele getAllele(int i) { + return genotype.getAllele(i); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index e4e97f4..3567354 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -1,51 +1,42 @@ package org.molgenis.vcf.inheritance.matcher; -import htsjdk.variant.variantcontext.VariantContext; -import htsjdk.variant.variantcontext.writer.VariantContextWriter; -import htsjdk.variant.variantcontext.writer.VariantContextWriterBuilder; -import htsjdk.variant.vcf.VCFFileReader; import htsjdk.variant.vcf.VCFHeader; import org.molgenis.vcf.inheritance.matcher.checker.ArCompoundChecker; import org.molgenis.vcf.inheritance.matcher.model.*; -import org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils; import org.molgenis.vcf.utils.metadata.FieldMetadataService; import org.molgenis.vcf.utils.sample.model.*; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import static java.lang.String.format; import static java.util.Collections.singletonMap; +import static java.util.Objects.requireNonNull; import static org.molgenis.vcf.inheritance.matcher.InheritanceMatcher.matchInheritance; import static org.molgenis.vcf.utils.sample.mapper.PedToSamplesMapper.mapPedFileToPedigrees; public class InheritanceService { - private final FieldMetadataService fieldMetadataService; private final Annotator annotator; + private final List pedigreePaths; + private final List probands; + private final VepMapper vepMapper; private ArCompoundChecker arCompoundChecker; private final PedigreeInheritanceChecker pedigreeInheritanceChecker; public InheritanceService( - Annotator annotator, FieldMetadataService fieldMetadataService, PedigreeInheritanceChecker pedigreeInheritanceChecker) { - this.annotator = annotator; - this.fieldMetadataService = fieldMetadataService; - this.pedigreeInheritanceChecker = pedigreeInheritanceChecker; - } + Annotator annotator, VepMapper vepMapper, PedigreeInheritanceChecker pedigreeInheritanceChecker, List pedigreePaths, List probands) { + this.annotator = requireNonNull(annotator); + this.vepMapper = requireNonNull(vepMapper); + this.pedigreeInheritanceChecker = requireNonNull(pedigreeInheritanceChecker); - public void run(Settings settings) { - Path inputVcf = settings.getInputVcfPath(); - List pedigreePaths = settings.getInputPedPaths(); - List probands = settings.getProbands(); - VCFFileReader vcfFileReader = createReader(inputVcf); + this.pedigreePaths = pedigreePaths; + this.probands = probands; + } - VepMapper vepMapper = new VepMapper(vcfFileReader, fieldMetadataService); + public void run(VcfReader vcfReader, RecordWriter recordWriter) { this.arCompoundChecker = new ArCompoundChecker(vepMapper); Map knownGenes = new HashMap<>(); @@ -53,50 +44,46 @@ public void run(Settings settings) { if (!pedigreePaths.isEmpty()) { familyList = mapPedFileToPedigrees(pedigreePaths); } else { - familyList = createFamilyFromVcf(vcfFileReader.getFileHeader()); - } - VCFHeader newHeader = annotator.annotateHeader(vcfFileReader.getFileHeader()); - try (VariantContextWriter writer = createVcfWriter(settings.getOutputPath(), - settings.isOverwrite())) { - writer.writeHeader(newHeader); - - List variantContextList = new ArrayList<>(); - vcfFileReader.forEach(variantContextList::add); - Map> geneVariantMap = createGeneVariantMap(vepMapper, knownGenes, - variantContextList); - variantContextList.stream().filter(vc -> vc.getAlternateAlleles().size() > 1).map( - vc -> processSingleVariantcontext(probands, vepMapper, familyList, - geneVariantMap, vc)).forEach(writer::add); - } catch (IOException ioException) { - throw new UncheckedIOException(ioException); + familyList = createFamilyFromVcf(vcfReader.getFileHeader()); } + VCFHeader newHeader = annotator.annotateHeader(vcfReader.getFileHeader()); + recordWriter.writeHeader(newHeader); + + List vcfRecordList = new ArrayList<>(); + vcfReader.stream().forEach(vcfRecordList::add); + Map> geneVariantMap = createGeneVariantMap(vepMapper, knownGenes, + vcfRecordList); + vcfRecordList.stream().filter(record -> !record.getAlternateAlleles().isEmpty()).map( + vcfRecord -> processSingleVariantcontext(probands, vepMapper, familyList, + geneVariantMap, vcfRecord)).forEach(recordWriter::add); + } - private VariantContext processSingleVariantcontext(List probands, VepMapper vepMapper, + private VcfRecord processSingleVariantcontext(List probands, VepMapper vepMapper, Map pedigreeList, - Map> geneVariantMap, VariantContext vc) { + Map> geneVariantMap, VcfRecord vcfRecord) { Map inheritanceMap = matchInheritanceForVariant(geneVariantMap, - vc, pedigreeList, probands); + vcfRecord, pedigreeList, probands); Map annotationMap = matchInheritance(inheritanceMap, - vepMapper.getGenes(vc)); - return annotator.annotateInheritance(vc, pedigreeList, annotationMap); + vepMapper.getGenes(vcfRecord)); + return annotator.annotateInheritance(vcfRecord, pedigreeList, annotationMap); } - private Map> createGeneVariantMap(VepMapper vepMapper, + private Map> createGeneVariantMap(VepMapper vepMapper, Map knownGenes, - List variantContextList) { - Map> geneVariantMap = new HashMap<>(); - for (VariantContext vc : variantContextList) { - VariantContextGenes variantContextGenes = vepMapper.getGenes(vc, knownGenes); + List vcfRecordList) { + Map> geneVariantMap = new HashMap<>(); + for (VcfRecord vcfRecord : vcfRecordList) { + VariantContextGenes variantContextGenes = vepMapper.getGenes(vcfRecord, knownGenes); knownGenes.putAll(variantContextGenes.getGenes()); for (Gene gene : variantContextGenes.getGenes().values()) { - List geneVariantList; + List geneVariantList; if (geneVariantMap.containsKey(gene.getId())) { geneVariantList = geneVariantMap.get(gene.getId()); } else { geneVariantList = new ArrayList<>(); } - geneVariantList.add(vc); + geneVariantList.add(vcfRecord); geneVariantMap.put(gene.getId(), geneVariantList); } } @@ -120,8 +107,8 @@ private Map createFamilyFromVcf(VCFHeader fileHeader) { } private Map matchInheritanceForVariant( - Map> geneVariantMap, - VariantContext variantContext, Map familyList, + Map> geneVariantMap, + VcfRecord record, Map familyList, List probands) { Map result = new HashMap<>(); for (Pedigree family : familyList.values()) { @@ -129,7 +116,7 @@ private Map matchInheritanceForVariant( if (probands.contains(sample.getPerson().getIndividualId()) || (probands.isEmpty() && sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED)) { result.put(sample.getPerson().getIndividualId(), - calculateInheritanceForFamily(geneVariantMap, variantContext, family, + calculateInheritanceForFamily(geneVariantMap, record, family, sample)); } } @@ -138,27 +125,10 @@ private Map matchInheritanceForVariant( } private Inheritance calculateInheritanceForFamily( - Map> geneVariantMap, - VariantContext variantContext, Pedigree family, + Map> geneVariantMap, + VcfRecord record, Pedigree family, Sample sample) { - return pedigreeInheritanceChecker.calculatePedigreeInheritance(geneVariantMap, variantContext, sample, family, arCompoundChecker); + return pedigreeInheritanceChecker.calculatePedigreeInheritance(geneVariantMap, record, sample, family, arCompoundChecker); } - private static VCFFileReader createReader(Path vcfPath) { - return new VCFFileReader(vcfPath, false); - } - - private static VariantContextWriter createVcfWriter(Path outputVcfPath, boolean overwrite) - throws IOException { - if (overwrite) { - Files.deleteIfExists(outputVcfPath); - } else if (Files.exists(outputVcfPath)) { - throw new IllegalArgumentException( - format("cannot create '%s' because it already exists.", outputVcfPath)); - } - return new VariantContextWriterBuilder() - .clearOptions() - .setOutputFile(outputVcfPath.toFile()) - .build(); - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java index 6f0c4f3..ff4abc5 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java @@ -1,7 +1,6 @@ package org.molgenis.vcf.inheritance.matcher; import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.VariantContext; import org.molgenis.vcf.inheritance.matcher.checker.*; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -39,67 +38,68 @@ public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, //TODO replace geneVariantMap with context incl pathogenic classes Inheritance calculatePedigreeInheritance( - Map> geneVariantMap, VariantContext variantContext, Sample sample, Pedigree filteredFamily, ArCompoundChecker arCompoundChecker) { + Map> geneVariantMap, VcfRecord record, Sample sample, Pedigree filteredFamily, ArCompoundChecker arCompoundChecker) { Inheritance inheritance = Inheritance.builder().build(); - checkAr(geneVariantMap, variantContext, filteredFamily, inheritance, arCompoundChecker); - checkAd(variantContext, filteredFamily, inheritance); - checkXl(variantContext, filteredFamily, inheritance); - checkMt(variantContext, filteredFamily, inheritance); - checkYl(variantContext, filteredFamily, inheritance); - inheritance.setDenovo(deNovoChecker.checkDeNovo(variantContext, sample)); + //FIXME + checkAr(geneVariantMap, record, filteredFamily, inheritance, arCompoundChecker); + checkAd(record, filteredFamily, inheritance); + checkXl(record, filteredFamily, inheritance); + checkMt(record, filteredFamily, inheritance); + checkYl(record, filteredFamily, inheritance); + inheritance.setDenovo(deNovoChecker.checkDeNovo(record, sample)); return inheritance; } - private void checkMt(VariantContext variantContext, Pedigree family, + private void checkMt(VcfRecord vcfRecord, Pedigree family, Inheritance inheritance) { - MatchEnum isMt = mtChecker.check(variantContext, family); + MatchEnum isMt = mtChecker.check(vcfRecord, family); if (isMt != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.MT, isMt == POTENTIAL)); } } - private void checkYl(VariantContext variantContext, Pedigree family, + private void checkYl(VcfRecord vcfRecord, Pedigree family, Inheritance inheritance) { - MatchEnum isYl = ylChecker.check(variantContext, family); + MatchEnum isYl = ylChecker.check(vcfRecord, family); if (isYl != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.YL, isYl == POTENTIAL)); } } - private void checkXl(VariantContext variantContext, Pedigree family, + private void checkXl(VcfRecord vcfRecord, Pedigree family, Inheritance inheritance) { - MatchEnum isXld = xldChecker.check(variantContext, family); + MatchEnum isXld = xldChecker.check(vcfRecord, family); if (isXld != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.XLD, isXld == POTENTIAL)); } - MatchEnum isXlr = xlrChecker.check(variantContext, family); + MatchEnum isXlr = xlrChecker.check(vcfRecord, family); if (isXlr != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.XLR, isXlr == POTENTIAL)); } } - private void checkAd(VariantContext variantContext, Pedigree family, + private void checkAd(VcfRecord vcfRecord, Pedigree family, Inheritance inheritance) { - MatchEnum isAd = adChecker.check(variantContext, family); + MatchEnum isAd = adChecker.check(vcfRecord, family); if (isAd != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AD, isAd == POTENTIAL)); } else { - MatchEnum isAdNonPenetrance = adNonPenetranceChecker.check(variantContext, family, isAd); + MatchEnum isAdNonPenetrance = adNonPenetranceChecker.check(vcfRecord, family, isAd); if (isAdNonPenetrance != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AD_IP, isAdNonPenetrance == POTENTIAL)); } } } - private void checkAr(Map> geneVariantMap, - VariantContext variantContext, Pedigree family, + private void checkAr(Map> geneVariantMap, + VcfRecord vcfRecord, Pedigree family, Inheritance inheritance, ArCompoundChecker arCompoundChecker) { - MatchEnum isAr = arChecker.check(variantContext, family); + MatchEnum isAr = arChecker.check(vcfRecord, family); if (isAr != FALSE) { inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AR, isAr == POTENTIAL)); } List compounds = arCompoundChecker - .check(geneVariantMap, variantContext, family, isAr); + .check(geneVariantMap, vcfRecord, family, isAr); if (!compounds.isEmpty()) { boolean isCertain = compounds.stream().anyMatch(CompoundCheckResult::isCertain); inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AR_C, !isCertain)); @@ -108,10 +108,10 @@ private void checkAr(Map> geneVariantMap, } } - private String createKey(VariantContext compound) { - return String.format("%s_%s_%s_%s", compound.getContig(), compound.getStart(), - compound.getReference().getBaseString(), - compound.getAlternateAlleles().stream().map(Allele::getBaseString) + private String createKey(VcfRecord vcfRecord) { + return String.format("%s_%s_%s_%s", vcfRecord.getContig(), vcfRecord.getStart(), + vcfRecord.getReference().getBaseString(), + vcfRecord.getAlternateAlleles().stream().map(Allele::getBaseString) .collect(Collectors.joining("/"))); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java new file mode 100644 index 0000000..b662afc --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java @@ -0,0 +1,11 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.vcf.VCFHeader; + +import java.io.Closeable; + +public interface RecordWriter { + void add(VcfRecord vcfRecord); + void writeHeader(VCFHeader vcfHeader); + void close(); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java new file mode 100644 index 0000000..eeca17e --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java @@ -0,0 +1,7 @@ +package org.molgenis.vcf.inheritance.matcher; + +import org.molgenis.vcf.inheritance.matcher.model.Settings; + +public interface RecordWriterFactory { + RecordWriter create(Settings settings); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java new file mode 100644 index 0000000..f7d08a1 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java @@ -0,0 +1,42 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.writer.VariantContextWriter; +import htsjdk.variant.variantcontext.writer.VariantContextWriterBuilder; +import org.molgenis.vcf.inheritance.matcher.model.Settings; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static java.lang.String.format; + +@Component +public class RecordWriterFactoryImpl implements RecordWriterFactory{ + @Override + public RecordWriter create(Settings settings) { + + VariantContextWriter vcfWriter = createVcfWriter(settings); + return new RecordWriterImpl(vcfWriter); + } + + private static VariantContextWriter createVcfWriter(Settings settings) { + Path outputVcfPath = settings.getOutputPath(); + if (settings.isOverwrite()) { + try { + Files.deleteIfExists(outputVcfPath); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } else if (Files.exists(outputVcfPath)) { + throw new IllegalArgumentException( + format("cannot create '%s' because it already exists.", outputVcfPath)); + } + + return new VariantContextWriterBuilder() + .clearOptions() + .setOutputFile(outputVcfPath.toFile()) + .build(); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java new file mode 100644 index 0000000..165753e --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java @@ -0,0 +1,31 @@ +package org.molgenis.vcf.inheritance.matcher; + +import static java.util.Objects.requireNonNull; +import htsjdk.variant.variantcontext.writer.VariantContextWriter; +import htsjdk.variant.vcf.VCFHeader; + +import java.io.Closeable; + +public class RecordWriterImpl implements RecordWriter, Closeable { + + private final VariantContextWriter vcfWriter; + + public RecordWriterImpl(VariantContextWriter vcfWriter) { + this.vcfWriter = requireNonNull(vcfWriter); + } + + @Override + public void writeHeader(VCFHeader vcfHeader) { + this.vcfWriter.writeHeader(vcfHeader); + } + + @Override + public void add(VcfRecord vcfRecord) { + this.vcfWriter.add(vcfRecord.unwrap()); + } + + @Override + public void close() { + this.vcfWriter.close(); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java index 44f7031..4421c89 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java @@ -7,23 +7,23 @@ public class VariantContextUtils { private VariantContextUtils() { } - public static boolean onAutosome(VariantContext variantContext) { - String contigId = variantContext.getContig(); + public static boolean onAutosome(VcfRecord vcfRecord) { + String contigId = vcfRecord.getContig(); return contigId != null && ContigUtils.isAutosome(contigId); } - public static boolean onChromosomeX(VariantContext variantContext) { - String contigId = variantContext.getContig(); + public static boolean onChromosomeX(VcfRecord vcfRecord) { + String contigId = vcfRecord.getContig(); return contigId != null && ContigUtils.isChromosomeX(contigId); } - public static boolean onChromosomeY(VariantContext variantContext) { - String contigId = variantContext.getContig(); + public static boolean onChromosomeY(VcfRecord vcfRecord) { + String contigId = vcfRecord.getContig(); return contigId != null && ContigUtils.isChromosomeY(contigId); } - public static boolean onChromosomeMt(VariantContext variantContext) { - String contigId = variantContext.getContig(); + public static boolean onChromosomeMt(VcfRecord vcfRecord) { + String contigId = vcfRecord.getContig(); return contigId != null && ContigUtils.isChromosomeMt(contigId); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java index 2114f86..22456b1 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java @@ -2,8 +2,13 @@ import static java.util.Objects.requireNonNull; +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFFileReader; +import htsjdk.variant.vcf.VCFHeader; +import java.util.Collections; +import java.util.List; import java.util.Set; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -14,27 +19,44 @@ public class VcfReader implements AutoCloseable { private final VCFFileReader vcfFileReader; + private final VepMapper vepMapper; + private final Set pathogenicClasses; - public VcfReader(VCFFileReader vcfFileReader) { + public VcfReader(VCFFileReader vcfFileReader, VepMapper vepMapper, Set pathogenicClasses) { this.vcfFileReader = requireNonNull(vcfFileReader); + this.vepMapper = vepMapper; + this.pathogenicClasses = pathogenicClasses; } public Stream stream() { - return StreamSupport.stream(vcfFileReader.spliterator(), false).map(VcfRecord::new); + //FIXME + return StreamSupport.stream(vcfFileReader.spliterator(), false).map(vc -> new VcfRecord(vc, getPathogenicAlleles(vc))); + } + + private List getPathogenicAlleles(VariantContext vc) { + if(pathogenicClasses.isEmpty()){ + return vc.getAlternateAlleles(); + } + //FIXME + return Collections.emptyList(); } public Stream filteredStream(Set classes) { //FIXME: filter on classes - return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(VcfRecord::new); + return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, getPathogenicAlleles(vc))); } public Stream filteredStream(Set classes, String geneId) { //FIXME: filter on classes and geneId - return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(VcfRecord::new); + return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, getPathogenicAlleles(vc))); } @Override public void close() { vcfFileReader.close(); } + + public VCFHeader getFileHeader() { + return vcfFileReader.getFileHeader(); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java index 95b13cd..51521b8 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java @@ -2,13 +2,23 @@ import htsjdk.variant.vcf.VCFFileReader; import org.molgenis.vcf.inheritance.matcher.model.Settings; +import org.molgenis.vcf.inheritance.matcher.util.VepMetadataServiceFactoryImpl; +import org.springframework.stereotype.Component; import java.nio.file.Path; -public class VcfReaderFactoryImpl implements VcfReaderFactory{ +@Component +public class VcfReaderFactoryImpl implements VcfReaderFactory { + private final VepMetadataServiceFactoryImpl vepMetadataServiceFactoryImpl; + + public VcfReaderFactoryImpl(VepMetadataServiceFactoryImpl vepMetadataServiceFactoryImpl) { + this.vepMetadataServiceFactoryImpl = vepMetadataServiceFactoryImpl; + } + @Override public VcfReader create(Settings settings) { Path inputVcfPath = settings.getInputVcfPath(); - return new VcfReader(new VCFFileReader(inputVcfPath.toFile(), false)); + VCFFileReader vcfFileReader = new VCFFileReader(inputVcfPath.toFile(), false); + return new VcfReader(vcfFileReader, new VepMapper(vcfFileReader.getFileHeader(), vepMetadataServiceFactoryImpl.create()), settings.getPathogenicClasses()); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java index 4eeecf7..c1461d1 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java @@ -1,17 +1,50 @@ package org.molgenis.vcf.inheritance.matcher; +import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.VariantContext; +import java.util.List; + import static java.util.Objects.requireNonNull; public class VcfRecord { VariantContext variantContext; + private final List pathogenicAlleles; - public VcfRecord(VariantContext variantContext) { + public VcfRecord(VariantContext variantContext, List pathogenicAlleles) { this.variantContext = requireNonNull(variantContext); + this.pathogenicAlleles = requireNonNull(pathogenicAlleles); } public Genotype getGenotype(String sampleId){ - return new Genotype(variantContext.getGenotype(sampleId)); + htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); + if(gt == null){ + return null; + } + return new Genotype(gt, variantContext, pathogenicAlleles); + } + + public List getAttributeAsStringList(String vepFieldId) { + return variantContext.getAttributeAsStringList(vepFieldId, ""); + } + + public List getAlternateAlleles() { + return variantContext.getAlternateAlleles(); + } + + public VariantContext unwrap() { + return variantContext; + } + + public String getContig() { + return variantContext.getContig(); + } + + public int getStart() { + return variantContext.getStart(); + } + + public Allele getReference() { + return variantContext.getReference(); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java index a607d8b..452fa31 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java @@ -2,8 +2,6 @@ import static java.util.Collections.emptyMap; -import htsjdk.variant.variantcontext.VariantContext; -import htsjdk.variant.vcf.VCFFileReader; import htsjdk.variant.vcf.VCFHeader; import htsjdk.variant.vcf.VCFInfoHeaderLine; import java.util.HashMap; @@ -28,16 +26,19 @@ public class VepMapper { "Consequence annotations from Ensembl VEP. Format: "; private static final String INHERITANCE = "InheritanceModesGene"; private String vepFieldId = null; - private final FieldMetadataService fieldMetadataService; + private final VCFHeader vcfHeader; + private final FieldMetadataService fieldMetadataService; private int geneIndex = -1; private int geneSourceIndex = -1; private int inheritanceIndex = -1; private int alleleNumIndex = -1; private int classIndex = -1; - public VepMapper(VCFFileReader vcfFileReader, FieldMetadataService fieldMetadataService) { - this.fieldMetadataService = fieldMetadataService; - init(vcfFileReader); + public VepMapper(VCFHeader vcfHeader, FieldMetadataService fieldMetadataService) { + this.vcfHeader = vcfHeader; + this.fieldMetadataService = fieldMetadataService; + + init(); } private static boolean canMap(VCFInfoHeaderLine vcfInfoHeaderLine) { @@ -46,8 +47,7 @@ private static boolean canMap(VCFInfoHeaderLine vcfInfoHeaderLine) { return description.startsWith(INFO_DESCRIPTION_PREFIX); } - private void init(VCFFileReader vcfFileReader) { - VCFHeader vcfHeader = vcfFileReader.getFileHeader(); + private void init() { for (VCFInfoHeaderLine vcfInfoHeaderLine : vcfHeader.getInfoHeaderLines()) { if (canMap(vcfInfoHeaderLine)) { this.vepFieldId = vcfInfoHeaderLine.getID(); @@ -65,14 +65,14 @@ private void init(VCFFileReader vcfFileReader) { throw new MissingInfoException("VEP"); } - public VariantContextGenes getGenes(VariantContext vc) { - return getGenes(vc, emptyMap()); + public VariantContextGenes getGenes(VcfRecord record) { + return getGenes(record, emptyMap()); } - public VariantContextGenes getGenes(VariantContext vc, Map knownGenes) { + public VariantContextGenes getGenes(VcfRecord record, Map knownGenes) { VariantContextGenes.VariantContextGenesBuilder genesBuilder = VariantContextGenes.builder(); Map genes = new HashMap<>(); - List vepValues = vc.getAttributeAsStringList(vepFieldId, ""); + List vepValues = record.getAttributeAsStringList(vepFieldId); for (String vepValue : vepValues) { String[] vepSplit = vepValue.split("\\|", -1); String gene = vepSplit[geneIndex]; @@ -98,8 +98,8 @@ public VariantContextGenes getGenes(VariantContext vc, Map knownGe return genesBuilder.build(); } - public Set getClassesForAllele(VariantContext vc, int alleleIndex){ - List vepValues = vc.getAttributeAsStringList(vepFieldId, ""); + public Set getClassesForAllele(VcfRecord record, int alleleIndex){ + List vepValues = record.getAttributeAsStringList(vepFieldId); Set classes = new HashSet<>(); for (String vepValue : vepValues) { String[] vepSplit = vepValue.split("\\|", -1); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index fb7ea1d..2a0dbfa 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -1,16 +1,14 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; - +import org.molgenis.vcf.inheritance.matcher.Genotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.hasVariant; /** * Autosomal dominant (AD) inheritance pattern matcher @@ -21,23 +19,23 @@ public class AdChecker extends InheritanceChecker{ * Check whether the AD inheritance pattern could match for a variant in a pedigree */ public MatchEnum check( - VariantContext variantContext, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantContext)) { + VcfRecord vcfRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(vcfRecord)) { return FALSE; } - return checkFamily(variantContext, family); + return checkFamily(vcfRecord, family); } - MatchEnum checkSample(Sample sample, VariantContext variantContext) { - Genotype sampleGt = variantContext.getGenotype(sample.getPerson().getIndividualId()); + MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); if (sampleGt == null || sampleGt.isNoCall()) { return POTENTIAL; } else { if (sampleGt.isMixed()) { return checkMixed(sample, sampleGt); } else { - if (hasVariant(sampleGt)) { + if (sampleGt.hasAltAllele()) { return checkSampleWithVariant(sample); } else { return checkSampleWithoutVariant(sample); @@ -65,12 +63,12 @@ private static MatchEnum checkSampleWithVariant(Sample sample) { private static MatchEnum checkMixed(Sample sample, Genotype sampleGt) { switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - if (!hasVariant(sampleGt)) { + if (!sampleGt.hasAltAllele()) { return POTENTIAL; } } case UNAFFECTED -> { - if (hasVariant(sampleGt)) { + if (sampleGt.hasAltAllele()) { return FALSE; } else { return POTENTIAL; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java index d82713b..0f84d3a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java @@ -1,11 +1,10 @@ package org.molgenis.vcf.inheritance.matcher.checker; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.hasVariant; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.Genotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -15,20 +14,20 @@ public class AdNonPenetranceChecker extends InheritanceChecker{ public MatchEnum check( - VariantContext variantContext, Pedigree family, MatchEnum isAd) { - if (!VariantContextUtils.onAutosome(variantContext) || isAd == TRUE) { + VcfRecord vcfRecord, Pedigree family, MatchEnum isAd) { + if (!VariantContextUtils.onAutosome(vcfRecord) || isAd == TRUE) { return FALSE; } - return checkFamily(variantContext, family); + return checkFamily(vcfRecord, family); } - MatchEnum checkSample(Sample sample, VariantContext variantContext) { - Genotype sampleGt = variantContext.getGenotype(sample.getPerson().getIndividualId()); + MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { if (sampleGt.isMixed()) { - return hasVariant(sampleGt) ? TRUE : POTENTIAL; + return sampleGt.hasAltAllele() ? TRUE : POTENTIAL; } if(sampleGt.isNoCall()){ return POTENTIAL; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java index f163e65..8b979f6 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java @@ -2,10 +2,9 @@ import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.hasVariant; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -15,24 +14,24 @@ public class ArChecker extends InheritanceChecker{ public MatchEnum check( - VariantContext variantContext, Pedigree family) { - if (!onAutosome(variantContext)) { + VcfRecord vcfRecord, Pedigree family) { + if (!onAutosome(vcfRecord)) { return FALSE; } - return checkFamily(variantContext, family); + return checkFamily(vcfRecord, family); } @Override - MatchEnum checkSample(Sample sample, VariantContext variantContext) { - Genotype sampleGt = variantContext.getGenotype(sample.getPerson().getIndividualId()); + MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); if (sampleGt == null || sampleGt.isNoCall()) { return POTENTIAL; } else { if (sampleGt.isMixed()) { return checkMixed(sample, sampleGt); } else { - if (hasVariant(sampleGt)) { + if (sampleGt.hasAltAllele()) { return checkSampleWithVariant(sample, sampleGt); } else { return checkSampleWithoutVariant(sample); @@ -60,7 +59,7 @@ private static MatchEnum checkSampleWithVariant(Sample sample, Genotype sampleGt private static MatchEnum checkMixed(Sample sample, Genotype sampleGt) { switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - if (!hasVariant(sampleGt)) { + if (!sampleGt.hasAltAllele()) { return FALSE; } else { return POTENTIAL; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index 1ea40f2..1d7bf2d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -2,15 +2,15 @@ import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.*; +import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.isAlt; import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.GenotypeBuilder; -import htsjdk.variant.variantcontext.VariantContext; import java.util.*; +import htsjdk.variant.variantcontext.GenotypeBuilder; +import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.VepMapper; import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; import org.molgenis.vcf.inheritance.matcher.model.Gene; @@ -27,29 +27,29 @@ public ArCompoundChecker(VepMapper vepMapper) { } public List check( - Map> geneVariantMap, - VariantContext variantContext, Pedigree family, MatchEnum isAr) { - if (onAutosome(variantContext) && isAr != TRUE) { + Map> geneVariantMap, + VcfRecord vcfRecord, Pedigree family, MatchEnum isAr) { + if (onAutosome(vcfRecord) && isAr != TRUE) { List compounds = new ArrayList<>(); - Map genes = vepMapper.getGenes(variantContext).getGenes(); + Map genes = vepMapper.getGenes(vcfRecord).getGenes(); for (Gene gene : genes.values()) { - checkForGene(geneVariantMap, variantContext, family, compounds, gene); + checkForGene(geneVariantMap, vcfRecord, family, compounds, gene); } return compounds; } return Collections.emptyList(); } - private void checkForGene(Map> geneVariantMap, - VariantContext variantContext, Pedigree family, List compounds, + private void checkForGene(Map> geneVariantMap, + VcfRecord vcfRecord, Pedigree family, List compounds, Gene gene) { - List variantContexts = geneVariantMap.get(gene.getId()); + List variantContexts = geneVariantMap.get(gene.getId()); if (variantContexts != null) { - for (VariantContext otherVariantContext : variantContexts) { - if (!otherVariantContext.equals(variantContext)) { - MatchEnum isPossibleCompound = checkFamily(family, variantContext, otherVariantContext); + for (VcfRecord otherRecord : variantContexts) { + if (!otherRecord.equals(vcfRecord)) { + MatchEnum isPossibleCompound = checkFamily(family, vcfRecord, otherRecord); if (isPossibleCompound != FALSE) { - CompoundCheckResult result = CompoundCheckResult.builder().possibleCompound(otherVariantContext).isCertain(isPossibleCompound != POTENTIAL).build(); + CompoundCheckResult result = CompoundCheckResult.builder().possibleCompound(otherRecord).isCertain(isPossibleCompound != POTENTIAL).build(); compounds.add(result); } } @@ -57,11 +57,11 @@ private void checkForGene(Map> geneVariantMap, } } - private MatchEnum checkFamily(Pedigree family, VariantContext variantContext, - VariantContext otherVariantContext) { + private MatchEnum checkFamily(Pedigree family, VcfRecord vcfRecord, + VcfRecord otherVcfRecord) { Set results = new HashSet<>(); for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, variantContext, otherVariantContext)); + results.add(checkSample(sample, vcfRecord, otherVcfRecord)); } if (results.contains(FALSE)) { return FALSE; @@ -71,15 +71,14 @@ private MatchEnum checkFamily(Pedigree family, VariantContext variantContext, return TRUE; } - private MatchEnum checkSample(Sample sample, VariantContext variantContext, VariantContext otherVariantContext) { + private MatchEnum checkSample(Sample sample, VcfRecord vcfRecord, VcfRecord otherVcfRecord) { //Affected individuals have to be het. for both variants //Healthy individuals can be het. for one of the variants but cannot have both variants - Genotype missingGenotype = GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2); - Genotype sampleGt = variantContext.getGenotype(sample.getPerson().getIndividualId()); - Genotype sampleOtherGt = otherVariantContext.getGenotype(sample.getPerson().getIndividualId()); - sampleGt = sampleGt != null ? sampleGt : missingGenotype; - sampleOtherGt = sampleOtherGt != null ? sampleOtherGt : missingGenotype; + Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + Genotype sampleOtherGt = otherVcfRecord.getGenotype(sample.getPerson().getIndividualId()); + sampleGt = sampleGt != null ? sampleGt : new Genotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), vcfRecord.unwrap(), Collections.emptyList()); + sampleOtherGt = sampleOtherGt != null ? sampleOtherGt : new Genotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), otherVcfRecord.unwrap(), Collections.emptyList()); return switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> checkAffectedSample(sampleGt, sampleOtherGt); case UNAFFECTED -> checkUnaffectedSample(sampleGt, sampleOtherGt); @@ -90,8 +89,8 @@ private MatchEnum checkSample(Sample sample, VariantContext variantContext, Vari private MatchEnum checkAffectedSample(Genotype sampleGt, Genotype sampleOtherGt) { if (sampleGt.isHomRef() || sampleOtherGt.isHomRef()) { return FALSE; - } else if (isHomAlt(sampleGt) - || isHomAlt(sampleOtherGt)) { + } else if (sampleGt.isHomAlt() + || sampleOtherGt.isHomAlt()) { return FALSE; } else if (sampleGt.isPhased() && sampleOtherGt.isPhased()) { return checkSamplePhased(sampleGt, sampleOtherGt, true); @@ -100,10 +99,10 @@ private MatchEnum checkAffectedSample(Genotype sampleGt, Genotype sampleOtherGt) } private MatchEnum checkUnaffectedSample(Genotype sampleGt, Genotype sampleOtherGt) { - if ((sampleGt.isNoCall() && (hasVariant(sampleOtherGt) || sampleOtherGt.isNoCall())) - || sampleOtherGt.isNoCall() && (hasVariant(sampleGt))) { + if ((sampleGt.isNoCall() && (sampleOtherGt.hasAltAllele() || sampleOtherGt.isNoCall())) + || sampleOtherGt.isNoCall() && (sampleGt.hasAltAllele())) { return POTENTIAL; - } else if (isHomAlt(sampleGt) || isHomAlt(sampleOtherGt)) { + } else if (sampleGt.isHomAlt() || sampleOtherGt.isHomAlt()) { return FALSE; } else if (sampleGt.isPhased() && sampleOtherGt.isPhased()) { return checkSamplePhased(sampleGt, sampleOtherGt, false); @@ -112,8 +111,8 @@ private MatchEnum checkUnaffectedSample(Genotype sampleGt, Genotype sampleOtherG } private MatchEnum checkUnaffectedSampleUnphased(Genotype sampleGt, Genotype sampleOtherGt) { - boolean sampleContainsAlt = hasVariant(sampleGt); - boolean sampleOtherGtContainsAlt = hasVariant(sampleOtherGt); + boolean sampleContainsAlt = sampleGt.hasAltAllele(); + boolean sampleOtherGtContainsAlt = sampleOtherGt.hasAltAllele(); if (sampleContainsAlt && sampleOtherGtContainsAlt) { return FALSE; } else if ((sampleContainsAlt || sampleGt.isMixed() || sampleGt.isNoCall()) && @@ -139,13 +138,13 @@ private MatchEnum checkSamplePhased(Genotype sampleGt, Genotype sampleOtherGt, b } private MatchEnum checkAffectedSampleUnphased(Genotype sampleGt, Genotype sampleOtherGt) { - if (hasVariant(sampleGt) && !sampleGt.isHom() && hasVariant(sampleOtherGt) && !sampleOtherGt.isHom()) { + if (sampleGt.hasAltAllele() && !sampleGt.isHom() && sampleOtherGt.hasAltAllele() && !sampleOtherGt.isHom()) { return TRUE; } boolean gtMissingOrMixed = sampleGt.isNoCall() || sampleGt.isMixed(); boolean otherGtMissingOrMixed = sampleOtherGt.isNoCall() || sampleOtherGt.isMixed(); - boolean hasVariantAndOtherGtMissing = (hasVariant(sampleGt) && !sampleGt.isHom() && otherGtMissingOrMixed); - boolean hasOtherVariantAndGtMissing = (gtMissingOrMixed && hasVariant(sampleOtherGt) && !sampleOtherGt.isHom()); + boolean hasVariantAndOtherGtMissing = sampleGt.hasAltAllele() && !sampleGt.isHom() && otherGtMissingOrMixed; + boolean hasOtherVariantAndGtMissing = gtMissingOrMixed && sampleOtherGt.hasAltAllele() && !sampleOtherGt.isHom(); if (hasVariantAndOtherGtMissing || hasOtherVariantAndGtMissing || (gtMissingOrMixed && otherGtMissingOrMixed)) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java index 6d0aac2..710e2b4 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java @@ -5,7 +5,7 @@ import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.*; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; import org.molgenis.vcf.utils.sample.model.Sex; @@ -14,17 +14,18 @@ @Component public class DeNovoChecker { - public MatchEnum checkDeNovo(VariantContext variantContext, Sample proband) { - Genotype probandGt = variantContext.getGenotype(proband.getPerson().getIndividualId()); - Genotype fatherGt = variantContext.getGenotype(proband.getPerson().getPaternalId()); - Genotype motherGt = variantContext.getGenotype(proband.getPerson().getMaternalId()); + //use original GT instead of inheritance matcher specific one since we are looking for "new alleles" not specifically pathogenic ones + public MatchEnum checkDeNovo(VcfRecord vcfRecord, Sample proband) { + Genotype probandGt = vcfRecord.getGenotype(proband.getPerson().getIndividualId()) != null ? vcfRecord.getGenotype(proband.getPerson().getIndividualId()).unwrap() : null; + Genotype fatherGt = vcfRecord.getGenotype(proband.getPerson().getPaternalId()) != null ? vcfRecord.getGenotype(proband.getPerson().getPaternalId()).unwrap() : null; + Genotype motherGt = vcfRecord.getGenotype(proband.getPerson().getMaternalId()) != null ? vcfRecord.getGenotype(proband.getPerson().getMaternalId()).unwrap() : null; if (!hasParents(proband)) { return POTENTIAL; } - if (onChromosomeX(variantContext) && proband.getPerson().getSex() == Sex.MALE) { - if (hasVariant(probandGt)) { - if (hasVariant(motherGt)) { + if (onChromosomeX(vcfRecord) && proband.getPerson().getSex() == Sex.MALE) { + if (probandGt.hasAltAllele()) { + if (motherGt.hasAltAllele()) { return FALSE; } else if (motherGt.isHomRef()) { return TRUE; @@ -33,9 +34,9 @@ public MatchEnum checkDeNovo(VariantContext variantContext, Sample proband) { } } return probandGt.isNoCall() ? POTENTIAL : FALSE; - } else if (onChromosomeY(variantContext)) { + } else if (onChromosomeY(vcfRecord)) { return checkYLinkedVariant(proband, probandGt, fatherGt); - } else if (onChromosomeMt(variantContext)) { + } else if (onChromosomeMt(vcfRecord)) { return checkMtVariant(probandGt, motherGt); } else { return checkRegular(probandGt, fatherGt, motherGt); @@ -49,34 +50,34 @@ private static MatchEnum checkYLinkedVariant(Sample proband, Genotype probandGt, case FEMALE: return FALSE; default: - return (hasVariant(fatherGt) || !hasVariant(probandGt)) ? FALSE : POTENTIAL; + return (fatherGt.hasAltAllele() || !probandGt.hasAltAllele()) ? FALSE : POTENTIAL; } } private static MatchEnum checkYLinkedVariantMale(Genotype probandGt, Genotype fatherGt) { - if (hasVariant(probandGt)) { - if (hasVariant(fatherGt)) { + if (probandGt.hasAltAllele()) { + if (fatherGt.hasAltAllele()) { return FALSE; } else { - return (!hasVariant(fatherGt) && !hasMissing(fatherGt)) ? TRUE : POTENTIAL; + return (!fatherGt.hasAltAllele() && !hasMissing(fatherGt)) ? TRUE : POTENTIAL; } } else if (hasMissing(probandGt)) { - return hasVariant(fatherGt) ? FALSE : POTENTIAL; + return fatherGt.hasAltAllele() ? FALSE : POTENTIAL; } return FALSE; } private static MatchEnum checkMtVariant(Genotype probandGt, Genotype motherGt) { - if (hasVariant(probandGt)) { - if (hasVariant(motherGt)) { + if (probandGt.hasAltAllele()) { + if (motherGt.hasAltAllele()) { return FALSE; - } else if (!hasVariant(motherGt) && motherGt.isCalled() && !motherGt.isMixed()) { + } else if (!motherGt.hasAltAllele() && motherGt.isCalled() && !motherGt.isMixed()) { return TRUE; } else { return POTENTIAL; } } else if (probandGt.isNoCall() || probandGt.isMixed()) { - if (hasVariant(motherGt)) { + if (motherGt.hasAltAllele()) { return FALSE; } else { return POTENTIAL; @@ -95,7 +96,7 @@ private MatchEnum checkRegular(Genotype probandGt, Genotype fatherGt, Genotype m } else if (probandGt.isMixed()) { result = checkMixed(probandGt, fatherGt, motherGt); } else { - result = (hasVariant(motherGt) && hasVariant(fatherGt)) ? FALSE : POTENTIAL; + result = (motherGt.hasAltAllele() && fatherGt.hasAltAllele()) ? FALSE : POTENTIAL; } } return result; @@ -103,16 +104,16 @@ private MatchEnum checkRegular(Genotype probandGt, Genotype fatherGt, Genotype m private static MatchEnum checkMixed(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { MatchEnum result; - if (hasVariant(probandGt)) { + if (probandGt.hasAltAllele()) { if (motherGt.isHomRef() && fatherGt.isHomRef()) { result = TRUE; - } else if (hasVariant(motherGt) && hasVariant(fatherGt)) { + } else if (motherGt.hasAltAllele() && fatherGt.hasAltAllele()) { result = FALSE; } else { result = POTENTIAL; } } else { - if (hasVariant(motherGt) || hasVariant(fatherGt)) { + if (motherGt.hasAltAllele() || fatherGt.hasAltAllele()) { result = FALSE; } else { result = POTENTIAL; @@ -122,10 +123,10 @@ private static MatchEnum checkMixed(Genotype probandGt, Genotype fatherGt, Genot } private static MatchEnum checkHetrozygote(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { - if (hasVariant(probandGt)) { + if (probandGt.hasAltAllele()) { if (motherGt.isHomRef() && fatherGt.isHomRef()) { return TRUE; - } else if (hasVariant(motherGt) || hasVariant(fatherGt)) { + } else if (motherGt.hasAltAllele() || fatherGt.hasAltAllele()) { return FALSE; } else { return POTENTIAL; @@ -135,10 +136,10 @@ private static MatchEnum checkHetrozygote(Genotype probandGt, Genotype fatherGt, } private static MatchEnum checkHomozygote(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { - if (hasVariant(probandGt)) { + if (probandGt.hasAltAllele()) { if (motherGt.isHomRef() || fatherGt.isHomRef()) { return TRUE; - } else if (hasVariant(motherGt) && hasVariant(fatherGt)) { + } else if (motherGt.hasAltAllele() && fatherGt.hasAltAllele()) { return FALSE; } else { return POTENTIAL; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java index 48e530e..c44bd68 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java @@ -1,16 +1,15 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.hasVariant; public abstract class HaploidChecker extends InheritanceChecker{ - protected MatchEnum checkSample(Sample sample, VariantContext variantContext) { - Genotype genotype = variantContext.getGenotype(sample.getPerson().getIndividualId()); + protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype genotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { return checkAffected(genotype); @@ -37,7 +36,7 @@ protected MatchEnum checkUnaffected(Genotype genotype) { } protected MatchEnum checkUnaffectedDiploid(Genotype genotype) { - if (hasVariant(genotype) || genotype.isMixed()) { + if (genotype.hasAltAllele()|| genotype.isMixed()) { return genotype.isHom() ? FALSE : POTENTIAL; } else { return genotype.isHomRef() ? TRUE : POTENTIAL; @@ -67,7 +66,7 @@ else if (genotype.getPloidy() == 2) { } protected MatchEnum checkAffectedDiploid(Genotype genotype) { - if (hasVariant(genotype)) { + if (genotype.hasAltAllele()) { return genotype.isHom() ? TRUE : POTENTIAL; } else if (genotype.isNoCall() || genotype.isMixed()) { return POTENTIAL; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java index 6d4f66f..ad7e875 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -12,10 +12,10 @@ public abstract class InheritanceChecker { - public MatchEnum checkFamily(VariantContext variantContext, Pedigree family) { + public MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { Set results = new HashSet<>(); for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, variantContext)); + results.add(checkSample(sample, vcfRecord)); } if(results.contains(FALSE)){ return FALSE; @@ -25,5 +25,5 @@ public MatchEnum checkFamily(VariantContext variantContext, Pedigree family) { return TRUE; } - abstract MatchEnum checkSample(Sample sample, VariantContext variantContext); + abstract MatchEnum checkSample(Sample sample, VcfRecord vcfRecord); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java index 9edafc2..1941804 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java @@ -1,6 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.springframework.stereotype.Component; @@ -10,10 +11,10 @@ @Component public class MtChecker extends HaploidChecker { - public MatchEnum check(VariantContext variantContext, Pedigree family) { - if (!onChromosomeMt(variantContext)) { + public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { + if (!onChromosomeMt(vcfRecord)) { return FALSE; } - return checkFamily(variantContext, family); + return checkFamily(vcfRecord, family); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java index 9d39a81..8318dcf 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java @@ -4,20 +4,20 @@ import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.utils.sample.model.Sex.FEMALE; import static org.molgenis.vcf.utils.sample.model.Sex.MALE; - -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +; +import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sex; public abstract class XlChecker extends InheritanceChecker{ - public MatchEnum check(VariantContext variantContext, Pedigree family) { - if (!onChromosomeX(variantContext)) { + public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { + if (!onChromosomeX(vcfRecord)) { return FALSE; } - return checkFamily(variantContext, family); + return checkFamily(vcfRecord, family); } protected Sex getSex(Sex sex, Genotype genotype) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index 25c9602..6fd51ae 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -1,20 +1,19 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.hasVariant; @Component public class XldChecker extends XlChecker { - protected MatchEnum checkSample(Sample sample, VariantContext variantContext) { - Genotype genotype = variantContext.getGenotype(sample.getPerson().getIndividualId()); + protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype genotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); if (genotype == null || !genotype.isCalled()) { return POTENTIAL; } @@ -40,14 +39,14 @@ private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { if (genotype.getAlleles().stream() .allMatch(Allele::isReference)) { return TRUE; - } else if (hasVariant(genotype)) { + } else if (genotype.hasAltAllele()) { return FALSE; } return POTENTIAL; } case FEMALE -> { // Healthy females can carry the variant (because of X inactivation) - if (genotype.isMixed() && hasVariant(genotype)) { + if (genotype.isMixed() && genotype.hasAltAllele()) { return POTENTIAL; } return (genotype.isHet() || genotype.isMixed() || genotype.isHomRef()) ? TRUE : FALSE; @@ -58,7 +57,7 @@ private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { private static MatchEnum checkAffected(Genotype genotype) { // Affected individuals have to be het. or hom. alt. - if (hasVariant(genotype)) { + if (genotype.hasAltAllele()) { return TRUE; } else { //homRef? then XLD==false, is any allele is missing than the match is "potential" diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index 2c8c02b..5b61732 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -1,19 +1,18 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.hasVariant; @Component public class XlrChecker extends XlChecker { - protected MatchEnum checkSample(Sample sample, VariantContext variantContext) { - Genotype genotype = variantContext.getGenotype(sample.getPerson().getIndividualId()); + protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype genotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); if (genotype == null || !genotype.isCalled()) { return POTENTIAL; } @@ -36,7 +35,7 @@ private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { switch (getSex(sample.getPerson().getSex(), genotype)) { case MALE -> { // Healthy males cannot carry the variant. - if (hasVariant(genotype)) { + if (genotype.hasAltAllele()) { return FALSE; } else if (genotype.isHomRef()) { return TRUE; @@ -45,9 +44,9 @@ private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { } case FEMALE -> { // Healthy females cannot be hom. alt. - if (hasVariant(genotype) && genotype.isHom()) { + if (genotype.hasAltAllele() && genotype.isHom()) { return FALSE; - } else if (hasVariant(genotype) && genotype.isMixed()) { + } else if (genotype.hasAltAllele() && genotype.isMixed()) { return POTENTIAL; } return TRUE; @@ -60,7 +59,7 @@ private MatchEnum checkAffected(Sample sample, Genotype genotype) { switch (getSex(sample.getPerson().getSex(), genotype)) { case MALE -> { // Affected males have to be het. or hom. alt. (het is theoretically not possible in males, but can occur due to Pseudo Autosomal Regions). - if (hasVariant(genotype)) { + if (genotype.hasAltAllele()) { return TRUE; } else if (genotype.isMixed()) { return POTENTIAL; @@ -71,7 +70,7 @@ private MatchEnum checkAffected(Sample sample, Genotype genotype) { // Affected females have to be hom. alt. if (genotype.isHomRef()) { return FALSE; - } else if (hasVariant(genotype) && genotype.isMixed()) { + } else if (genotype.hasAltAllele() && genotype.isMixed()) { return POTENTIAL; } return genotype.isHom() ? TRUE : FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java index 9158d85..ab34d0d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -15,22 +15,22 @@ @Component public class YlChecker extends HaploidChecker{ - public MatchEnum check(VariantContext variantContext, Pedigree family) { - if (!onChromosomeY(variantContext)) { + public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { + if (!onChromosomeY(vcfRecord)) { return FALSE; } - return checkFamily(variantContext, family); + return checkFamily(vcfRecord, family); } @Override - public MatchEnum checkFamily(VariantContext variantContext, Pedigree family) { + public MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { Set results = new HashSet<>(); for (Sample sample : family.getMembers().values()) { if (sample.getPerson().getSex() == Sex.FEMALE) { //female familty members do not play a role in Y-linked inheritance results.add(TRUE); } else { - results.add(checkSample(sample, variantContext)); + results.add(checkSample(sample, vcfRecord)); } } if (results.contains(FALSE)) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java index d4b514e..24c0dd8 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java @@ -2,10 +2,11 @@ import htsjdk.variant.variantcontext.VariantContext; import lombok.Builder; import lombok.Value; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; @Value @Builder public class CompoundCheckResult { - VariantContext possibleCompound; + VcfRecord possibleCompound; boolean isCertain; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java index 84610cc..21ff709 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Settings.java @@ -2,18 +2,19 @@ import java.nio.file.Path; import java.util.List; +import java.util.Set; + import lombok.Builder; import lombok.Value; @Value @Builder public class Settings { - Path inputVcfPath; List inputPedPaths; Path outputPath; List probands; - List pathogenicClasses; + Set pathogenicClasses; boolean overwrite; boolean debug; boolean strict; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java index 478df39..cf51338 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java @@ -1,7 +1,9 @@ package org.molgenis.vcf.inheritance.matcher.util; import org.molgenis.vcf.inheritance.matcher.InheritanceService; +import org.molgenis.vcf.inheritance.matcher.VepMapper; +import org.molgenis.vcf.inheritance.matcher.model.Settings; public interface InheritanceServiceFactory { - InheritanceService create(); + InheritanceService create(Settings settings, VepMapper vepMapper); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java index 2ce34d5..e46eb8d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java @@ -1,8 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.util; -import org.molgenis.vcf.inheritance.matcher.Annotator; -import org.molgenis.vcf.inheritance.matcher.InheritanceService; -import org.molgenis.vcf.inheritance.matcher.PedigreeInheritanceChecker; +import org.molgenis.vcf.inheritance.matcher.*; +import org.molgenis.vcf.inheritance.matcher.model.Settings; import org.springframework.stereotype.Component; import static java.util.Objects.requireNonNull; @@ -13,17 +12,15 @@ @Component public class InheritanceServiceFactoryImpl implements InheritanceServiceFactory { private final Annotator annotator; - private final VepMetadataServiceFactory vepMetadataServiceFactory; private final PedigreeInheritanceChecker pedigreeInheritanceChecker; - public InheritanceServiceFactoryImpl(Annotator annotator, VepMetadataServiceFactory vepMetadataServiceFactory, PedigreeInheritanceChecker pedigreeInheritanceChecker) { + public InheritanceServiceFactoryImpl(Annotator annotator, PedigreeInheritanceChecker pedigreeInheritanceChecker) { this.annotator = requireNonNull(annotator); - this.vepMetadataServiceFactory = requireNonNull(vepMetadataServiceFactory); this.pedigreeInheritanceChecker = requireNonNull(pedigreeInheritanceChecker); } @Override - public InheritanceService create() { - return new InheritanceService(annotator, vepMetadataServiceFactory.create(), pedigreeInheritanceChecker); + public InheritanceService create(Settings settings, VepMapper vepMapper) { + return new InheritanceService(annotator, vepMapper, pedigreeInheritanceChecker, settings.getInputPedPaths(), settings.getProbands()); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java index 13cb04a..512e2aa 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java @@ -12,18 +12,11 @@ public static boolean hasParents(Sample sample) { return !(sample.getPerson().getMaternalId().isEmpty() || sample.getPerson().getMaternalId().equals("0")) && !(sample.getPerson().getPaternalId().isEmpty() || sample.getPerson().getPaternalId().equals("0")); } - public static boolean hasVariant(Genotype genotype) { - return genotype != null && genotype.getAlleles().stream() - .anyMatch(allele -> allele.isCalled() && allele.isNonReference()); - } public static boolean hasMissing(Genotype genotype) { return genotype == null || genotype.getAlleles().stream() .anyMatch(Allele::isNoCall); } - public static boolean isHomAlt(Genotype genotype) { - return !genotype.isMixed() && !genotype.isNoCall() && !genotype.isHomRef() && genotype.isHom(); - } public static boolean isAlt(Allele allele) { return allele.isCalled() && allele.isNonReference(); diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java index a50c52a..7e5494a 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java @@ -1,7 +1,6 @@ package org.molgenis.vcf.inheritance.matcher; -import static java.util.Collections.emptySet; -import static java.util.Collections.singleton; +import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -152,7 +151,7 @@ void annotateInheritance() { Set.of("GENE1", "GENE2")).build(); Map annotationMap = Map.of("Patient", annotation); - VariantContext actual = annotator.annotateInheritance(vc, families, annotationMap); + VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, emptyList()), families, annotationMap).unwrap(); assertAll( () -> assertEquals("AD_IP,AR_C", @@ -183,7 +182,7 @@ void annotateInheritanceMissingGeneInheritancePattern() { Annotation annotation = Annotation.builder().inheritance(inheritance).build(); Map annotationMap = Map.of("Patient", annotation); - VariantContext actual = annotator.annotateInheritance(vc, families, annotationMap); + VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, emptyList()), families, annotationMap).unwrap(); assertAll( () -> assertEquals("AD_IP,AR_C", @@ -212,7 +211,7 @@ void annotateInheritanceNoMatch() { Annotation annotation = Annotation.builder().inheritance(inheritance).build(); Map annotationMap = Map.of("Patient", annotation); - VariantContext actual = annotator.annotateInheritance(vc, families, annotationMap); + VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, emptyList()), families, annotationMap).unwrap(); assertAll( () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MODES)), diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java index d7d77e8..0664570 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java @@ -54,7 +54,7 @@ void testProband() throws IOException { String pedigree = ResourceUtils.getFile("classpath:pedigree_complex.ped").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); @@ -71,7 +71,7 @@ void testNoParents() throws IOException { String pedigree = ResourceUtils.getFile("classpath:pedigree_fam_no_parents.ped").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java index a9cd357..189e45c 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java @@ -19,8 +19,7 @@ import java.util.Map; import java.util.Set; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; +import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -55,21 +54,22 @@ void setUp() { @Test void testAdIpPotential() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(FALSE); - when(xlrChecker.check(vc, family)).thenReturn(FALSE); - when(adChecker.check(vc, family)).thenReturn(FALSE); - when(arChecker.check(vc, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(vc, family, FALSE)).thenReturn(POTENTIAL); - when(mtChecker.check(vc, family)).thenReturn(FALSE); - when(ylChecker.check(vc, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, vc, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(FALSE); + when(xlrChecker.check(record, family)).thenReturn(FALSE); + when(adChecker.check(record, family)).thenReturn(FALSE); + when(arChecker.check(record, family)).thenReturn(FALSE); + when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(POTENTIAL); + when(mtChecker.check(record, family)).thenReturn(FALSE); + when(ylChecker.check(record, family)).thenReturn(FALSE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); + Map> geneMap = emptyMap(); + when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.AD_IP, true))).denovo(FALSE).build(); assertEquals(expected, actual); @@ -78,21 +78,22 @@ void testAdIpPotential() { @Test void testXlRDTrue() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(TRUE); - when(xlrChecker.check(vc, family)).thenReturn(TRUE); - when(adChecker.check(vc, family)).thenReturn(FALSE); - when(arChecker.check(vc, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(vc, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(vc, family)).thenReturn(FALSE); - when(ylChecker.check(vc, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, vc, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(TRUE); + when(xlrChecker.check(record, family)).thenReturn(TRUE); + when(adChecker.check(record, family)).thenReturn(FALSE); + when(arChecker.check(record, family)).thenReturn(FALSE); + when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); + when(mtChecker.check(record, family)).thenReturn(FALSE); + when(ylChecker.check(record, family)).thenReturn(FALSE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); + Map> geneMap = emptyMap(); + when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches( Set.of(new PedigreeInheritanceMatch(InheritanceMode.XLD, false), new PedigreeInheritanceMatch(InheritanceMode.XLR, false))).denovo(FALSE).build(); @@ -103,19 +104,20 @@ void testXlRDTrue() { @Test void testArAdMixed() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(FALSE); - when(xlrChecker.check(vc, family)).thenReturn(FALSE); - when(adChecker.check(vc, family)).thenReturn(TRUE); - when(arChecker.check(vc, family)).thenReturn(POTENTIAL); - when(mtChecker.check(vc, family)).thenReturn(FALSE); - when(ylChecker.check(vc, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(FALSE); + when(xlrChecker.check(record, family)).thenReturn(FALSE); + when(adChecker.check(record, family)).thenReturn(TRUE); + when(arChecker.check(record, family)).thenReturn(POTENTIAL); + when(mtChecker.check(record, family)).thenReturn(FALSE); + when(ylChecker.check(record, family)).thenReturn(FALSE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); + Map> geneMap = emptyMap(); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches( Set.of(new PedigreeInheritanceMatch(InheritanceMode.AD, false), new PedigreeInheritanceMatch(InheritanceMode.AR, true))).denovo(FALSE).build(); @@ -126,20 +128,21 @@ void testArAdMixed() { @Test void testAdDenovoMixed() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(FALSE); - when(xlrChecker.check(vc, family)).thenReturn(FALSE); - when(adChecker.check(vc, family)).thenReturn(TRUE); - when(arChecker.check(vc, family)).thenReturn(FALSE); - when(mtChecker.check(vc, family)).thenReturn(FALSE); - when(ylChecker.check(vc, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(TRUE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, vc, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(FALSE); + when(xlrChecker.check(record, family)).thenReturn(FALSE); + when(adChecker.check(record, family)).thenReturn(TRUE); + when(arChecker.check(record, family)).thenReturn(FALSE); + when(mtChecker.check(record, family)).thenReturn(FALSE); + when(ylChecker.check(record, family)).thenReturn(FALSE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(TRUE); + Map> geneMap = emptyMap(); + when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches( Set.of(new PedigreeInheritanceMatch(InheritanceMode.AD, false))).denovo(TRUE).build(); @@ -149,6 +152,7 @@ void testAdDenovoMixed() { @Test void testArPotential() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); VariantContext vc2 = mock(VariantContext.class); Allele ref = mock(Allele.class); when(ref.getBaseString()).thenReturn("A"); @@ -158,21 +162,22 @@ void testArPotential() { when(vc2.getStart()).thenReturn(123); when(vc2.getReference()).thenReturn(ref); when(vc2.getAlternateAlleles()).thenReturn(List.of(alt)); + VcfRecord record2 = new VcfRecord(vc2, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(FALSE); - when(xlrChecker.check(vc, family)).thenReturn(FALSE); - when(adChecker.check(vc, family)).thenReturn(FALSE); - when(arChecker.check(vc, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(vc, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(vc, family)).thenReturn(FALSE); - when(ylChecker.check(vc, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, vc, family, FALSE)).thenReturn(List.of(CompoundCheckResult.builder().possibleCompound(vc2).isCertain(false).build())); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(FALSE); + when(xlrChecker.check(record, family)).thenReturn(FALSE); + when(adChecker.check(record, family)).thenReturn(FALSE); + when(arChecker.check(record, family)).thenReturn(FALSE); + when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); + when(mtChecker.check(record, family)).thenReturn(FALSE); + when(ylChecker.check(record, family)).thenReturn(FALSE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); + Map> geneMap = emptyMap(); + when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(List.of(CompoundCheckResult.builder().possibleCompound(record2).isCertain(false).build())); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.AR_C, true))).compounds(Set.of("chr1_123_A_T")).denovo(FALSE).build(); assertEquals(expected, actual); @@ -181,21 +186,22 @@ void testArPotential() { @Test void testMtPotential() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(FALSE); - when(xlrChecker.check(vc, family)).thenReturn(FALSE); - when(adChecker.check(vc, family)).thenReturn(FALSE); - when(arChecker.check(vc, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(vc, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(vc, family)).thenReturn(POTENTIAL); - when(ylChecker.check(vc, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, vc, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(FALSE); + when(xlrChecker.check(record, family)).thenReturn(FALSE); + when(adChecker.check(record, family)).thenReturn(FALSE); + when(arChecker.check(record, family)).thenReturn(FALSE); + when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); + when(mtChecker.check(record, family)).thenReturn(POTENTIAL); + when(ylChecker.check(record, family)).thenReturn(FALSE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); + Map> geneMap = emptyMap(); + when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.MT, true))).denovo(FALSE).build(); assertEquals(expected, actual); @@ -204,21 +210,22 @@ void testMtPotential() { @Test void testYl() { VariantContext vc = mock(VariantContext.class); + VcfRecord record = new VcfRecord(vc, emptyList()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(vc, family)).thenReturn(FALSE); - when(xlrChecker.check(vc, family)).thenReturn(FALSE); - when(adChecker.check(vc, family)).thenReturn(FALSE); - when(arChecker.check(vc, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(vc, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(vc, family)).thenReturn(FALSE); - when(ylChecker.check(vc, family)).thenReturn(TRUE); - when(deNovoChecker.checkDeNovo(vc, sample)).thenReturn(TRUE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, vc, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, vc, sample, family, arCompoundChecker); + when(xldChecker.check(record, family)).thenReturn(FALSE); + when(xlrChecker.check(record, family)).thenReturn(FALSE); + when(adChecker.check(record, family)).thenReturn(FALSE); + when(arChecker.check(record, family)).thenReturn(FALSE); + when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); + when(mtChecker.check(record, family)).thenReturn(FALSE); + when(ylChecker.check(record, family)).thenReturn(TRUE); + when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(TRUE); + Map> geneMap = emptyMap(); + when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); + + Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.YL, false))).denovo(TRUE).build(); assertEquals(expected, actual); diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java index 7b35984..1a1a710 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java @@ -14,7 +14,7 @@ class VariantContextUtilsTest { @Mock - private VariantContext variantContext; + private VcfRecord variantContext; @Test void onAutosomeTrue() { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java index 5c1780f..bf79854 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java @@ -1,5 +1,7 @@ package org.molgenis.vcf.inheritance.matcher; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -11,7 +13,6 @@ import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.XLR; import htsjdk.variant.variantcontext.VariantContext; -import htsjdk.variant.vcf.VCFFileReader; import htsjdk.variant.vcf.VCFHeader; import htsjdk.variant.vcf.VCFInfoHeaderLine; import java.util.Arrays; @@ -44,7 +45,7 @@ class VepMapperTest { @BeforeEach void setUp() { - VCFFileReader vcfFileReader = mock(VCFFileReader.class); + VcfReader vcfReader = mock(VcfReader.class); VCFHeader header = mock(VCFHeader.class); VCFInfoHeaderLine infoHeader = mock(VCFInfoHeaderLine.class); when(infoHeader.getID()).thenReturn("CSQ"); @@ -71,8 +72,7 @@ void setUp() { when(fieldMetadataService.load(infoHeader)).thenReturn( FieldMetadata.builder().nestedFields(vepMeta).build()); when(header.getInfoHeaderLines()).thenReturn(Collections.singletonList(infoHeader)); - when(vcfFileReader.getFileHeader()).thenReturn(header); - vepMapper = new VepMapper(vcfFileReader, fieldMetadataService); + vepMapper = new VepMapper(header, fieldMetadataService); } @Test @@ -86,7 +86,7 @@ void getGenes() { .genes(Map.of("ENSG00000123457", new Gene("ENSG00000123457","HGNC", Set.of(XLD, XLR)), "ENSG00000123456", new Gene("ENSG00000123456","HGNC", Set.of(AD, AR)), "ENSG00000123458", new Gene("ENSG00000123458","HGNC", Set.of(XLD, XLR)))).build(); - assertEquals(expected, vepMapper.getGenes(vc)); + assertEquals(expected, vepMapper.getGenes(new VcfRecord(vc, emptyList()))); } @Test @@ -100,7 +100,7 @@ void getGenesEmptyValues() { VariantContextGenes expected = VariantContextGenes.builder().containsVcWithoutGene(true).genes(Map .of("ENSG00000123457", new Gene("ENSG00000123457", "HGNC", Set.of(XLD, XLR)), "ENSG00000123456", new Gene("ENSG00000123456", "HGNC", Set.of(AD, AR)))).build(); - assertEquals(expected, vepMapper.getGenes(vc2)); + assertEquals(expected, vepMapper.getGenes(new VcfRecord(vc2, emptyList()))); } @Test @@ -109,6 +109,6 @@ void getGenesEmptySymbolSource() { when(variantContext.getAttributeAsStringList(eq("CSQ"), any())).thenReturn(List.of( "G|missense_variant|MODERATE|TEST1|ENSG00000123456|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>G|ENSP00000366410.1:p.Arg207Gly|763|619|207|R/G|Cgg/Ggg|||1|||17877||AD&AR|Leber_congenital_amaurosis_9:AR|")); - assertEquals(VariantContextGenes.builder().genes(Map.of()).containsVcWithoutGene(true).build(), vepMapper.getGenes(variantContext)); + assertEquals(VariantContextGenes.builder().genes(Map.of()).containsVcWithoutGene(true).build(), vepMapper.getGenes(new VcfRecord(variantContext, emptyList()))); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java index 9fd5736..199226d 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,10 +32,10 @@ class AdCheckerTest { final AdChecker adChecker = new AdChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, - String displayName) { + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adChecker.check(variantContext, family)); + assertEquals(expected, adChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java index af55ac5..06097c4 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java @@ -1,5 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.FALSE; @@ -22,6 +24,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -35,17 +38,17 @@ class AdNonPenCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, - String displayName) { + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adNonPenetranceChecker.check(variantContext, family, FALSE)); + assertEquals(expected, adNonPenetranceChecker.check(vcfRecord, family, FALSE)); } @Test void testCheckAd() { VariantContext variantContext = mock(VariantContext.class); Pedigree family = mock(Pedigree.class); - assertEquals(FALSE, adNonPenetranceChecker.check(variantContext, family, MatchEnum.TRUE)); + assertEquals(FALSE, adNonPenetranceChecker.check(new VcfRecord(variantContext, emptyList()), family, MatchEnum.TRUE)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java index 92d6a0e..282ae83 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java @@ -18,6 +18,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,10 +32,10 @@ class ArCheckerTest { final ArChecker arChecker = new ArChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, - String displayName) { + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, arChecker.check(variantContext, family)); + assertEquals(expected, arChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java index 63969b7..270b701 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java @@ -26,6 +26,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.VepMapper; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; @@ -43,13 +44,13 @@ class ArCompoundCheckerTest { @ParameterizedTest(name = "{index} {4}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Map> geneVariantMap, + void check(VcfRecord vcfRecord, Map> geneVariantMap, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); ArCompoundChecker arCompoundChecker = new ArCompoundChecker(vepMapper); - when(vepMapper.getGenes(variantContext)).thenReturn(VariantContextGenes.builder().genes(singletonMap("GENE1", gene1)).build()); - List compounds = arCompoundChecker.check(geneVariantMap, variantContext, family, FALSE); + when(vepMapper.getGenes(vcfRecord)).thenReturn(VariantContextGenes.builder().genes(singletonMap("GENE1", gene1)).build()); + List compounds = arCompoundChecker.check(geneVariantMap, vcfRecord, family, FALSE); if(expected == FALSE) { assertTrue(compounds.isEmpty()); }else if(expected == TRUE){ diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java index 581c91c..b78edc7 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java @@ -15,6 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -28,11 +29,11 @@ class DeNovoCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, - String displayName) { + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + String displayName) { MatchEnum expected = mapExpectedString(expectedString); Sample individual = family.getMembers().get("Patient"); - assertEquals(expected, deNovoChecker.checkDeNovo(variantContext, individual)); + assertEquals(expected, deNovoChecker.checkDeNovo(vcfRecord, individual)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java index 31b1b3b..49cca07 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -33,10 +34,10 @@ class MtCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, mtChecker.check(variantContext, family)); + assertEquals(expected, mtChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java index 32e8f49..a0e91b9 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -29,10 +30,10 @@ class XldCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, - String displayName) { + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xldChecker.check(variantContext, family)); + assertEquals(expected, xldChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java index eb9446f..ffbf4b1 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -29,10 +30,10 @@ class XlrCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, - String displayName) { + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xlrChecker.check(variantContext, family)); + assertEquals(expected, xlrChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java index f500a1e..2bab9c4 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java @@ -7,6 +7,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -33,10 +34,10 @@ class YlCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantContext variantContext, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, ylChecker.check(variantContext, family)); + assertEquals(expected, ylChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java index ef0f7f3..008f041 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java @@ -5,27 +5,28 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.Annotator; -import org.molgenis.vcf.inheritance.matcher.PedigreeInheritanceChecker; +import org.molgenis.vcf.inheritance.matcher.*; +import org.molgenis.vcf.inheritance.matcher.model.Settings; -import static org.mockito.Mockito.verify; +import static org.junit.jupiter.api.Assertions.assertNotNull; @ExtendWith(MockitoExtension.class) class InheritanceServiceFactoryImplTest { @Mock private Annotator annotator; @Mock - private VepMetadataServiceFactory vepMetadataServiceFactory; + private VepMapper vepMapper; @Mock private PedigreeInheritanceChecker pedigreeInheritanceChecker; + private InheritanceServiceFactoryImpl inheritanceServiceFactoryImpl; @BeforeEach void setUp() { - inheritanceServiceFactoryImpl = new InheritanceServiceFactoryImpl(annotator, vepMetadataServiceFactory, pedigreeInheritanceChecker); + inheritanceServiceFactoryImpl = new InheritanceServiceFactoryImpl(annotator, pedigreeInheritanceChecker); } @Test void create() { - inheritanceServiceFactoryImpl.create(); - verify(vepMetadataServiceFactory).create(); + InheritanceService inheritanceServiceFactory = inheritanceServiceFactoryImpl.create(Settings.builder().build(), vepMapper); + assertNotNull(inheritanceServiceFactory); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java index ea442f3..ca8702e 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java @@ -5,12 +5,15 @@ import htsjdk.variant.variantcontext.GenotypeBuilder; import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.variantcontext.VariantContextBuilder; +import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; public class VariantContextTestUtil { @@ -18,11 +21,11 @@ public class VariantContextTestUtil { public static final Allele REF = Allele.REF_T; public static final Allele ALT = Allele.ALT_A; - public static VariantContext createVariantContext(List genotypes, String vep) { + public static VcfRecord createVariantContext(List genotypes, String vep) { return createVariantContext(genotypes, vep, "1"); } - public static VariantContext createVariantContext(List genotypes, String vep, + public static VcfRecord createVariantContext(List genotypes, String vep, String contig) { VariantContextBuilder builder = new VariantContextBuilder(); builder.chr(contig); @@ -31,7 +34,7 @@ public static VariantContext createVariantContext(List genotypes, Stri builder.alleles(Arrays.asList(REF, ALT)); builder.genotypes(genotypes); builder.attribute("CSQ", vep); - return builder.make(); + return new VcfRecord(builder.make(), emptyList()); } public static Genotype createGenotype(String sample, String gt) { diff --git a/src/test/resources/integration.vcf b/src/test/resources/integration.vcf index fd01193..ea52846 100644 --- a/src/test/resources/integration.vcf +++ b/src/test/resources/integration.vcf @@ -36,4 +36,17 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 +1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 +1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 +1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 +1 123460 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +1 123461 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|1|AD GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 +2 1 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 +3 2 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 +4 123457 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +4 123458 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +X 123457 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5||XLR,G|GENE7|EntrezGene|ID7||XLD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 +X 123458 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 +X 123459 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6||XLR GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 From 648113efadfcbce11d6dc45bcb26452be9e1ee17 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 4 Sep 2024 11:50:51 +0200 Subject: [PATCH 03/28] Use effective genotype in inheritance matching --- .../matcher/EffectiveGenotype.java | 102 ++++++++++++++++++ .../vcf/inheritance/matcher/Genotype.java | 95 ---------------- .../vcf/inheritance/matcher/VcfRecord.java | 4 +- .../matcher/checker/AdChecker.java | 6 +- .../checker/AdNonPenetranceChecker.java | 4 +- .../matcher/checker/ArChecker.java | 8 +- .../matcher/checker/ArCompoundChecker.java | 20 ++-- .../matcher/checker/HaploidChecker.java | 66 ++++++------ .../matcher/checker/XlChecker.java | 4 +- .../matcher/checker/XldChecker.java | 28 ++--- .../matcher/checker/XlrChecker.java | 36 +++---- 11 files changed, 190 insertions(+), 183 deletions(-) create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java new file mode 100644 index 0000000..0b57961 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java @@ -0,0 +1,102 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.Genotype; +import htsjdk.variant.variantcontext.GenotypeBuilder; +import htsjdk.variant.variantcontext.VariantContext; + +import java.util.List; + +import static java.util.Objects.requireNonNull; + +public class EffectiveGenotype { + htsjdk.variant.variantcontext.Genotype originalGenotype; + private final VariantContext variantContext; + private final List pathogenicAlleles; + private Genotype effectiveGenotype; + + public EffectiveGenotype(htsjdk.variant.variantcontext.Genotype originalGenotype, VariantContext variantContext, List pathogenicAlleles) { + this.originalGenotype = requireNonNull(originalGenotype); + this.variantContext = requireNonNull(variantContext); + this.pathogenicAlleles = requireNonNull(pathogenicAlleles); + + init(); + } + + public htsjdk.variant.variantcontext.Genotype unwrap() { + return originalGenotype; + } + + //Consider Benign allele as a REF allele + private void init() { + if (originalGenotype.isNoCall()) { + effectiveGenotype = originalGenotype; + } + GenotypeBuilder genotypeBuilder = new GenotypeBuilder(originalGenotype); + genotypeBuilder.alleles(originalGenotype.getAlleles().stream().map(this::mapAllele).toList()); + effectiveGenotype = genotypeBuilder.make(); + } + + private Allele mapAllele(Allele allele) { + if (isPathogenic(allele) || allele.isNoCall()) { + return allele; + } + return variantContext.getReference(); + } + + private boolean isPathogenic(Allele allele) { + //if no pathogenic classes are provided consider all ALTs pathogenic + if (allele.isNonReference() && pathogenicAlleles.isEmpty()) { + return true; + } + return pathogenicAlleles.contains(allele); + } + + public boolean isHomRef() { + return effectiveGenotype.isHomRef(); + } + + public boolean isNoCall() { + return effectiveGenotype.isNoCall(); + } + + public boolean isMixed() { + return effectiveGenotype.isMixed(); + } + + public int getPloidy() { + return effectiveGenotype.getPloidy(); + } + + public boolean isCalled() { + return effectiveGenotype.isCalled(); + } + + public boolean isHom() { + return effectiveGenotype.isHom(); + } + + public boolean hasAltAllele() { + return effectiveGenotype.hasAltAllele(); + } + + public List getAlleles() { + return effectiveGenotype.getAlleles(); + } + + public boolean isHet() { + return effectiveGenotype.isHet(); + } + + public boolean isPhased() { + return effectiveGenotype.isPhased(); + } + + public boolean isHomAlt() { + return effectiveGenotype.isHomVar(); + } + + public Allele getAllele(int i) { + return effectiveGenotype.getAllele(i); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java deleted file mode 100644 index ed9bc81..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Genotype.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.GenotypeBuilder; -import htsjdk.variant.variantcontext.VariantContext; -import java.util.List; - -import static java.util.Objects.requireNonNull; - -public class Genotype { - htsjdk.variant.variantcontext.Genotype genotype; - private final VariantContext variantContext; - private final List pathogenicAlleles; - - public Genotype(htsjdk.variant.variantcontext.Genotype genotype, VariantContext variantContext, List pathogenicAlleles) { - this.genotype = requireNonNull(genotype); - this.variantContext = requireNonNull(variantContext); - this.pathogenicAlleles = requireNonNull(pathogenicAlleles); - } - - public htsjdk.variant.variantcontext.Genotype unwrap() { - return genotype; - } - - //Consider Benign allele as a REF allele - //FIXME: private - public htsjdk.variant.variantcontext.Genotype getEffectiveGenotype() { - if (genotype.isNoCall()) { - return genotype; - } - return GenotypeBuilder.create(genotype.getSampleName(), genotype.getAlleles().stream().map(this::mapAllele).toList()); - } - - private Allele mapAllele(Allele allele) { - if(isBenign(allele)){ - return variantContext.getReference(); - } - return allele; - } - - private boolean isBenign(Allele allele) { - return !this.pathogenicAlleles.contains(allele); - } - - public boolean isHomRef() { - //TODO:implement - return genotype.isHomRef(); - } - - public boolean isNoCall() { - //TODO:implement - return genotype.isNoCall(); - } - - public boolean isMixed() { - //TODO:implement - return genotype.isMixed(); - } - - public int getPloidy() { - return genotype.getPloidy(); - } - - public boolean isCalled() { - return genotype.isCalled(); - } - - public boolean isHom() { - return genotype.isHom(); - } - - public boolean hasAltAllele() { - return genotype.hasAltAllele(); - } - - public List getAlleles() { - return genotype.getAlleles(); - } - - public boolean isHet() { - return genotype.isHet(); - } - - public boolean isPhased() { - return genotype.isPhased(); - } - - public boolean isHomAlt() { - return genotype.isHomVar(); - } - - public Allele getAllele(int i) { - return genotype.getAllele(i); - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java index c1461d1..4c45c86 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java @@ -16,12 +16,12 @@ public VcfRecord(VariantContext variantContext, List pathogenicAlleles) this.pathogenicAlleles = requireNonNull(pathogenicAlleles); } - public Genotype getGenotype(String sampleId){ + public EffectiveGenotype getGenotype(String sampleId){ htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); if(gt == null){ return null; } - return new Genotype(gt, variantContext, pathogenicAlleles); + return new EffectiveGenotype(gt, variantContext, pathogenicAlleles); } public List getAttributeAsStringList(String vepFieldId) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index 2a0dbfa..b9482c9 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -28,7 +28,7 @@ public MatchEnum check( } MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); if (sampleGt == null || sampleGt.isNoCall()) { return POTENTIAL; } else { @@ -60,7 +60,7 @@ private static MatchEnum checkSampleWithVariant(Sample sample) { }; } - private static MatchEnum checkMixed(Sample sample, Genotype sampleGt) { + private static MatchEnum checkMixed(Sample sample, EffectiveGenotype sampleGt) { switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { if (!sampleGt.hasAltAllele()) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java index 0f84d3a..0fb3314 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java @@ -2,7 +2,7 @@ import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -23,7 +23,7 @@ public MatchEnum check( } MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { if (sampleGt.isMixed()) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java index 8b979f6..bd99c61 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java @@ -3,7 +3,7 @@ import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -24,7 +24,7 @@ public MatchEnum check( @Override MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); if (sampleGt == null || sampleGt.isNoCall()) { return POTENTIAL; } else { @@ -48,7 +48,7 @@ private static MatchEnum checkSampleWithoutVariant(Sample sample) { }; } - private static MatchEnum checkSampleWithVariant(Sample sample, Genotype sampleGt) { + private static MatchEnum checkSampleWithVariant(Sample sample, EffectiveGenotype sampleGt) { return switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> sampleGt.isHom() ? TRUE : FALSE; case UNAFFECTED -> sampleGt.isHet() ? TRUE : FALSE; @@ -56,7 +56,7 @@ private static MatchEnum checkSampleWithVariant(Sample sample, Genotype sampleGt }; } - private static MatchEnum checkMixed(Sample sample, Genotype sampleGt) { + private static MatchEnum checkMixed(Sample sample, EffectiveGenotype sampleGt) { switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { if (!sampleGt.hasAltAllele()) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index 1d7bf2d..2d73b87 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -9,7 +9,7 @@ import java.util.*; import htsjdk.variant.variantcontext.GenotypeBuilder; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.VepMapper; import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; @@ -75,10 +75,10 @@ private MatchEnum checkSample(Sample sample, VcfRecord vcfRecord, VcfRecord othe //Affected individuals have to be het. for both variants //Healthy individuals can be het. for one of the variants but cannot have both variants - Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - Genotype sampleOtherGt = otherVcfRecord.getGenotype(sample.getPerson().getIndividualId()); - sampleGt = sampleGt != null ? sampleGt : new Genotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), vcfRecord.unwrap(), Collections.emptyList()); - sampleOtherGt = sampleOtherGt != null ? sampleOtherGt : new Genotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), otherVcfRecord.unwrap(), Collections.emptyList()); + EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + EffectiveGenotype sampleOtherGt = otherVcfRecord.getGenotype(sample.getPerson().getIndividualId()); + sampleGt = sampleGt != null ? sampleGt : new EffectiveGenotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), vcfRecord.unwrap(), Collections.emptyList()); + sampleOtherGt = sampleOtherGt != null ? sampleOtherGt : new EffectiveGenotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), otherVcfRecord.unwrap(), Collections.emptyList()); return switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> checkAffectedSample(sampleGt, sampleOtherGt); case UNAFFECTED -> checkUnaffectedSample(sampleGt, sampleOtherGt); @@ -86,7 +86,7 @@ private MatchEnum checkSample(Sample sample, VcfRecord vcfRecord, VcfRecord othe }; } - private MatchEnum checkAffectedSample(Genotype sampleGt, Genotype sampleOtherGt) { + private MatchEnum checkAffectedSample(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { if (sampleGt.isHomRef() || sampleOtherGt.isHomRef()) { return FALSE; } else if (sampleGt.isHomAlt() @@ -98,7 +98,7 @@ private MatchEnum checkAffectedSample(Genotype sampleGt, Genotype sampleOtherGt) return checkAffectedSampleUnphased(sampleGt, sampleOtherGt); } - private MatchEnum checkUnaffectedSample(Genotype sampleGt, Genotype sampleOtherGt) { + private MatchEnum checkUnaffectedSample(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { if ((sampleGt.isNoCall() && (sampleOtherGt.hasAltAllele() || sampleOtherGt.isNoCall())) || sampleOtherGt.isNoCall() && (sampleGt.hasAltAllele())) { return POTENTIAL; @@ -110,7 +110,7 @@ private MatchEnum checkUnaffectedSample(Genotype sampleGt, Genotype sampleOtherG return checkUnaffectedSampleUnphased(sampleGt, sampleOtherGt); } - private MatchEnum checkUnaffectedSampleUnphased(Genotype sampleGt, Genotype sampleOtherGt) { + private MatchEnum checkUnaffectedSampleUnphased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { boolean sampleContainsAlt = sampleGt.hasAltAllele(); boolean sampleOtherGtContainsAlt = sampleOtherGt.hasAltAllele(); if (sampleContainsAlt && sampleOtherGtContainsAlt) { @@ -122,7 +122,7 @@ private MatchEnum checkUnaffectedSampleUnphased(Genotype sampleGt, Genotype samp return TRUE; } - private MatchEnum checkSamplePhased(Genotype sampleGt, Genotype sampleOtherGt, boolean isAffected) { + private MatchEnum checkSamplePhased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt, boolean isAffected) { Allele allele1 = sampleGt.getAllele(0); Allele allele2 = sampleGt.getAllele(1); Allele otherAllele1 = sampleOtherGt.getAllele(0); @@ -137,7 +137,7 @@ private MatchEnum checkSamplePhased(Genotype sampleGt, Genotype sampleOtherGt, b return POTENTIAL; } - private MatchEnum checkAffectedSampleUnphased(Genotype sampleGt, Genotype sampleOtherGt) { + private MatchEnum checkAffectedSampleUnphased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { if (sampleGt.hasAltAllele() && !sampleGt.isHom() && sampleOtherGt.hasAltAllele() && !sampleOtherGt.isHom()) { return TRUE; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java index c44bd68..696827c 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; @@ -9,13 +9,13 @@ public abstract class HaploidChecker extends InheritanceChecker{ protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - Genotype genotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + EffectiveGenotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - return checkAffected(genotype); + return checkAffected(effectiveGenotype); } case UNAFFECTED -> { - return checkUnaffected(genotype); + return checkUnaffected(effectiveGenotype); } case MISSING -> { return POTENTIAL; @@ -24,62 +24,62 @@ protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { } } - protected MatchEnum checkUnaffected(Genotype genotype) { - if (genotype.getPloidy() == 1) { - return checkUnaffectedHaploid(genotype); - } else if (genotype.getPloidy() == 2) { - return checkUnaffectedDiploid(genotype); - } else if (genotype.isCalled()) { - throw new UnsupportedOperationException(String.format("Incompatible ploidy '%s' for haploid check''", genotype.getPloidy())); + protected MatchEnum checkUnaffected(EffectiveGenotype effectiveGenotype) { + if (effectiveGenotype.getPloidy() == 1) { + return checkUnaffectedHaploid(effectiveGenotype); + } else if (effectiveGenotype.getPloidy() == 2) { + return checkUnaffectedDiploid(effectiveGenotype); + } else if (effectiveGenotype.isCalled()) { + throw new UnsupportedOperationException(String.format("Incompatible ploidy '%s' for haploid check''", effectiveGenotype.getPloidy())); } return POTENTIAL; } - protected MatchEnum checkUnaffectedDiploid(Genotype genotype) { - if (genotype.hasAltAllele()|| genotype.isMixed()) { - return genotype.isHom() ? FALSE : POTENTIAL; + protected MatchEnum checkUnaffectedDiploid(EffectiveGenotype effectiveGenotype) { + if (effectiveGenotype.hasAltAllele()|| effectiveGenotype.isMixed()) { + return effectiveGenotype.isHom() ? FALSE : POTENTIAL; } else { - return genotype.isHomRef() ? TRUE : POTENTIAL; + return effectiveGenotype.isHomRef() ? TRUE : POTENTIAL; } } - protected MatchEnum checkUnaffectedHaploid(Genotype genotype) { - if (genotype.isNoCall()) { + protected MatchEnum checkUnaffectedHaploid(EffectiveGenotype effectiveGenotype) { + if (effectiveGenotype.isNoCall()) { return POTENTIAL; } - if (genotype.hasAltAllele()) { + if (effectiveGenotype.hasAltAllele()) { return FALSE; } return TRUE; } - protected MatchEnum checkAffected(Genotype genotype) { - if (genotype.getPloidy() == 1) { - return checkAffectedHaploid(genotype); + protected MatchEnum checkAffected(EffectiveGenotype effectiveGenotype) { + if (effectiveGenotype.getPloidy() == 1) { + return checkAffectedHaploid(effectiveGenotype); } - else if (genotype.getPloidy() == 2) { - return checkAffectedDiploid(genotype); - } else if (genotype.isCalled()) { - throw new UnsupportedOperationException(String.format("Incompatible ploidy '%s' for YL check", genotype.getPloidy())); + else if (effectiveGenotype.getPloidy() == 2) { + return checkAffectedDiploid(effectiveGenotype); + } else if (effectiveGenotype.isCalled()) { + throw new UnsupportedOperationException(String.format("Incompatible ploidy '%s' for YL check", effectiveGenotype.getPloidy())); } return POTENTIAL; } - protected MatchEnum checkAffectedDiploid(Genotype genotype) { - if (genotype.hasAltAllele()) { - return genotype.isHom() ? TRUE : POTENTIAL; - } else if (genotype.isNoCall() || genotype.isMixed()) { + protected MatchEnum checkAffectedDiploid(EffectiveGenotype effectiveGenotype) { + if (effectiveGenotype.hasAltAllele()) { + return effectiveGenotype.isHom() ? TRUE : POTENTIAL; + } else if (effectiveGenotype.isNoCall() || effectiveGenotype.isMixed()) { return POTENTIAL; } else { - return genotype.isHomRef() ? FALSE : POTENTIAL; + return effectiveGenotype.isHomRef() ? FALSE : POTENTIAL; } } - protected MatchEnum checkAffectedHaploid(Genotype genotype) { - if (genotype.isNoCall()) { + protected MatchEnum checkAffectedHaploid(EffectiveGenotype effectiveGenotype) { + if (effectiveGenotype.isNoCall()) { return POTENTIAL; } - if (genotype.hasAltAllele()) { + if (effectiveGenotype.hasAltAllele()) { return TRUE; } return FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java index 8318dcf..a24bdee 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java @@ -5,7 +5,7 @@ import static org.molgenis.vcf.utils.sample.model.Sex.FEMALE; import static org.molgenis.vcf.utils.sample.model.Sex.MALE; ; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -20,7 +20,7 @@ public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { return checkFamily(vcfRecord, family); } - protected Sex getSex(Sex sex, Genotype genotype) { + protected Sex getSex(Sex sex, EffectiveGenotype genotype) { if (sex == Sex.UNKNOWN) { //UNKNOWN? use best guess based on number of alleles if (genotype.getAlleles().size() == 1) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index 6fd51ae..2128f56 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; @@ -13,17 +13,17 @@ public class XldChecker extends XlChecker { protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - Genotype genotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - if (genotype == null || !genotype.isCalled()) { + EffectiveGenotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + if (effectiveGenotype == null || !effectiveGenotype.isCalled()) { return POTENTIAL; } switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - return checkAffected(genotype); + return checkAffected(effectiveGenotype); } case UNAFFECTED -> { - return checkUnaffected(sample, genotype); + return checkUnaffected(sample, effectiveGenotype); } case MISSING -> { return POTENTIAL; @@ -32,36 +32,36 @@ protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { } } - private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { - switch (getSex(sample.getPerson().getSex(), genotype)) { + private MatchEnum checkUnaffected(Sample sample, EffectiveGenotype effectiveGenotype) { + switch (getSex(sample.getPerson().getSex(), effectiveGenotype)) { case MALE -> { // Healthy males cannot carry the variant - if (genotype.getAlleles().stream() + if (effectiveGenotype.getAlleles().stream() .allMatch(Allele::isReference)) { return TRUE; - } else if (genotype.hasAltAllele()) { + } else if (effectiveGenotype.hasAltAllele()) { return FALSE; } return POTENTIAL; } case FEMALE -> { // Healthy females can carry the variant (because of X inactivation) - if (genotype.isMixed() && genotype.hasAltAllele()) { + if (effectiveGenotype.isMixed() && effectiveGenotype.hasAltAllele()) { return POTENTIAL; } - return (genotype.isHet() || genotype.isMixed() || genotype.isHomRef()) ? TRUE : FALSE; + return (effectiveGenotype.isHet() || effectiveGenotype.isMixed() || effectiveGenotype.isHomRef()) ? TRUE : FALSE; } default -> throw new IllegalArgumentException(); } } - private static MatchEnum checkAffected(Genotype genotype) { + private static MatchEnum checkAffected(EffectiveGenotype effectiveGenotype) { // Affected individuals have to be het. or hom. alt. - if (genotype.hasAltAllele()) { + if (effectiveGenotype.hasAltAllele()) { return TRUE; } else { //homRef? then XLD==false, is any allele is missing than the match is "potential" - return genotype.isHomRef() ? FALSE : POTENTIAL; + return effectiveGenotype.isHomRef() ? FALSE : POTENTIAL; } } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index 5b61732..cee5c1c 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; @@ -12,17 +12,17 @@ public class XlrChecker extends XlChecker { protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - Genotype genotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - if (genotype == null || !genotype.isCalled()) { + EffectiveGenotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + if (effectiveGenotype == null || !effectiveGenotype.isCalled()) { return POTENTIAL; } switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - return checkAffected(sample, genotype); + return checkAffected(sample, effectiveGenotype); } case UNAFFECTED -> { - return checkUnaffected(sample, genotype); + return checkUnaffected(sample, effectiveGenotype); } case MISSING -> { return POTENTIAL; @@ -31,22 +31,22 @@ protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { } } - private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { - switch (getSex(sample.getPerson().getSex(), genotype)) { + private MatchEnum checkUnaffected(Sample sample, EffectiveGenotype effectiveGenotype) { + switch (getSex(sample.getPerson().getSex(), effectiveGenotype)) { case MALE -> { // Healthy males cannot carry the variant. - if (genotype.hasAltAllele()) { + if (effectiveGenotype.hasAltAllele()) { return FALSE; - } else if (genotype.isHomRef()) { + } else if (effectiveGenotype.isHomRef()) { return TRUE; } return null; } case FEMALE -> { // Healthy females cannot be hom. alt. - if (genotype.hasAltAllele() && genotype.isHom()) { + if (effectiveGenotype.hasAltAllele() && effectiveGenotype.isHom()) { return FALSE; - } else if (genotype.hasAltAllele() && genotype.isMixed()) { + } else if (effectiveGenotype.hasAltAllele() && effectiveGenotype.isMixed()) { return POTENTIAL; } return TRUE; @@ -55,25 +55,25 @@ private MatchEnum checkUnaffected(Sample sample, Genotype genotype) { } } - private MatchEnum checkAffected(Sample sample, Genotype genotype) { - switch (getSex(sample.getPerson().getSex(), genotype)) { + private MatchEnum checkAffected(Sample sample, EffectiveGenotype effectiveGenotype) { + switch (getSex(sample.getPerson().getSex(), effectiveGenotype)) { case MALE -> { // Affected males have to be het. or hom. alt. (het is theoretically not possible in males, but can occur due to Pseudo Autosomal Regions). - if (genotype.hasAltAllele()) { + if (effectiveGenotype.hasAltAllele()) { return TRUE; - } else if (genotype.isMixed()) { + } else if (effectiveGenotype.isMixed()) { return POTENTIAL; } return FALSE; } case FEMALE -> { // Affected females have to be hom. alt. - if (genotype.isHomRef()) { + if (effectiveGenotype.isHomRef()) { return FALSE; - } else if (genotype.hasAltAllele() && genotype.isMixed()) { + } else if (effectiveGenotype.hasAltAllele() && effectiveGenotype.isMixed()) { return POTENTIAL; } - return genotype.isHom() ? TRUE : FALSE; + return effectiveGenotype.isHom() ? TRUE : FALSE; } default -> throw new IllegalArgumentException(); } From e41ab23a843f50978422701d916d021653ab0743 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 5 Sep 2024 07:32:03 +0200 Subject: [PATCH 04/28] Refactor VepMetadata --- .../vcf/inheritance/matcher/Annotator.java | 4 +- .../matcher/AppRunnerFactoryImpl.java | 5 +- .../matcher/InheritanceMatcher.java | 4 +- .../matcher/InheritanceService.java | 29 ++-- .../vcf/inheritance/matcher/VcfReader.java | 24 +--- .../matcher/VcfReaderFactoryImpl.java | 2 +- .../vcf/inheritance/matcher/VcfRecord.java | 93 ++++++++++++- .../vcf/inheritance/matcher/VepMapper.java | 131 ------------------ .../vcf/inheritance/matcher/VepMetadata.java | 76 ++++++++++ .../matcher/checker/ArCompoundChecker.java | 10 +- ...tContextGenes.java => VcfRecordGenes.java} | 3 +- .../util/InheritanceServiceFactory.java | 4 +- .../util/InheritanceServiceFactoryImpl.java | 4 +- .../inheritance/matcher/AnnotatorTest.java | 10 +- .../matcher/InheritanceMatcherTest.java | 12 +- .../PedigreeInheritanceCheckerTest.java | 19 +-- ...epMapperTest.java => VepMetadataTest.java} | 23 +-- .../matcher/checker/AdCheckerTest.java | 5 +- .../matcher/checker/AdNonPenCheckerTest.java | 9 +- .../matcher/checker/ArCheckerTest.java | 3 +- .../checker/ArCompoundCheckerTest.java | 13 +- .../matcher/checker/DeNovoCheckerTest.java | 3 +- .../matcher/checker/MtCheckerTest.java | 3 +- .../matcher/checker/XldCheckerTest.java | 3 +- .../matcher/checker/XlrCheckerTest.java | 3 +- .../matcher/checker/YlCheckerTest.java | 3 +- .../InheritanceServiceFactoryImplTest.java | 4 +- .../matcher/util/VariantContextTestUtil.java | 12 +- 28 files changed, 273 insertions(+), 241 deletions(-) delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java rename src/main/java/org/molgenis/vcf/inheritance/matcher/model/{VariantContextGenes.java => VcfRecordGenes.java} (80%) rename src/test/java/org/molgenis/vcf/inheritance/matcher/{VepMapperTest.java => VepMetadataTest.java} (88%) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 32670b2..509729d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -70,7 +70,6 @@ VCFHeader annotateHeader(VCFHeader vcfHeader) { VcfRecord annotateInheritance(VcfRecord vcfRecord, Map familyMap, Map annotationMap) { - //FIXME GenotypesContext genotypesContext = GenotypesContext.copy(vcfRecord.unwrap().getGenotypes()); VariantContextBuilder variantContextBuilder = new VariantContextBuilder(vcfRecord.unwrap()); for (Entry sampleFamilyEntry : familyMap.entrySet()) { @@ -81,8 +80,7 @@ VcfRecord annotateInheritance(VcfRecord vcfRecord, Map familyM } } } - //FIXME - return new VcfRecord(variantContextBuilder.genotypes(genotypesContext).make(), Collections.emptyList()); + return new VcfRecord(variantContextBuilder.genotypes(genotypesContext).make(), vcfRecord.getVepMetadata(), vcfRecord.getPathogenicClasses()); } private void annotateGenotype(VcfRecord vcfRecord, Annotation annotation, diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java index 7b765b0..01b46ff 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java @@ -3,7 +3,6 @@ import org.molgenis.vcf.inheritance.matcher.model.Settings; import org.molgenis.vcf.inheritance.matcher.util.InheritanceServiceFactory; import org.molgenis.vcf.inheritance.matcher.util.VepMetadataServiceFactory; -import org.molgenis.vcf.utils.metadata.FieldMetadataService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -36,10 +35,10 @@ class AppRunnerFactoryImpl implements AppRunnerFactory { @Override public AppRunner create(Settings settings) { VcfReader vcfReader = vcfReaderFactory.create(settings); - VepMapper vepMapper = new VepMapper(vcfReader.getFileHeader(), vepMetadataServiceFactory.create()); + VepMetadata vepMetadata = new VepMetadata(vcfReader.getFileHeader(), vepMetadataServiceFactory.create()); try { RecordWriter recordWriter = recordWriterFactory.create(settings); - return new AppRunnerImpl(vcfReader, recordWriter, inheritanceServiceFactory.create(settings, vepMapper)); + return new AppRunnerImpl(vcfReader, recordWriter, inheritanceServiceFactory.create(settings, vepMetadata)); } catch (Exception e) { try { vcfReader.close(); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java index b42397e..745d144 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java @@ -18,7 +18,7 @@ private InheritanceMatcher() { } public static Map matchInheritance( - Map inheritanceMap, VariantContextGenes genes) { + Map inheritanceMap, VcfRecordGenes genes) { Map sampleAnnotationMap = new HashMap<>(); for (Entry entry : inheritanceMap.entrySet()) { Set matchingGenes = new HashSet<>(); @@ -45,7 +45,7 @@ public static Map matchInheritance( * - inheritance match is unknown if any genes for the variant have unknown inheritance pattern. * - inheritance match is false if all genes for the variant have known (but mismatching) inheritance pattern. */ - private static void matchGeneInheritance(VariantContextGenes genes, Set matchingGenes, Inheritance pedigreeInheritance) { + private static void matchGeneInheritance(VcfRecordGenes genes, Set matchingGenes, Inheritance pedigreeInheritance) { boolean containsUnknownGene = false; for (Gene gene : genes.getGenes().values()) { Set geneInheritanceModes = gene diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index 3567354..70d7d00 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -3,7 +3,6 @@ import htsjdk.variant.vcf.VCFHeader; import org.molgenis.vcf.inheritance.matcher.checker.ArCompoundChecker; import org.molgenis.vcf.inheritance.matcher.model.*; -import org.molgenis.vcf.utils.metadata.FieldMetadataService; import org.molgenis.vcf.utils.sample.model.*; import java.nio.file.Path; @@ -22,14 +21,14 @@ public class InheritanceService { private final Annotator annotator; private final List pedigreePaths; private final List probands; - private final VepMapper vepMapper; + private final VepMetadata vepMetadata; private ArCompoundChecker arCompoundChecker; private final PedigreeInheritanceChecker pedigreeInheritanceChecker; public InheritanceService( - Annotator annotator, VepMapper vepMapper, PedigreeInheritanceChecker pedigreeInheritanceChecker, List pedigreePaths, List probands) { + Annotator annotator, VepMetadata vepMetadata, PedigreeInheritanceChecker pedigreeInheritanceChecker, List pedigreePaths, List probands) { this.annotator = requireNonNull(annotator); - this.vepMapper = requireNonNull(vepMapper); + this.vepMetadata = requireNonNull(vepMetadata); this.pedigreeInheritanceChecker = requireNonNull(pedigreeInheritanceChecker); this.pedigreePaths = pedigreePaths; @@ -37,7 +36,7 @@ public InheritanceService( } public void run(VcfReader vcfReader, RecordWriter recordWriter) { - this.arCompoundChecker = new ArCompoundChecker(vepMapper); + this.arCompoundChecker = new ArCompoundChecker(vepMetadata); Map knownGenes = new HashMap<>(); Map familyList; @@ -51,32 +50,32 @@ public void run(VcfReader vcfReader, RecordWriter recordWriter) { List vcfRecordList = new ArrayList<>(); vcfReader.stream().forEach(vcfRecordList::add); - Map> geneVariantMap = createGeneVariantMap(vepMapper, knownGenes, + Map> geneVariantMap = createGeneVariantMap(vepMetadata, knownGenes, vcfRecordList); vcfRecordList.stream().filter(record -> !record.getAlternateAlleles().isEmpty()).map( - vcfRecord -> processSingleVariantcontext(probands, vepMapper, familyList, + vcfRecord -> processSingleVariantcontext(probands, vepMetadata, familyList, geneVariantMap, vcfRecord)).forEach(recordWriter::add); } - private VcfRecord processSingleVariantcontext(List probands, VepMapper vepMapper, + private VcfRecord processSingleVariantcontext(List probands, VepMetadata vepMetadata, Map pedigreeList, Map> geneVariantMap, VcfRecord vcfRecord) { Map inheritanceMap = matchInheritanceForVariant(geneVariantMap, vcfRecord, pedigreeList, probands); Map annotationMap = matchInheritance(inheritanceMap, - vepMapper.getGenes(vcfRecord)); + vcfRecord.getVcfRecordGenes()); return annotator.annotateInheritance(vcfRecord, pedigreeList, annotationMap); } - private Map> createGeneVariantMap(VepMapper vepMapper, - Map knownGenes, - List vcfRecordList) { + private Map> createGeneVariantMap(VepMetadata vepMetadata, + Map knownGenes, + List vcfRecordList) { Map> geneVariantMap = new HashMap<>(); for (VcfRecord vcfRecord : vcfRecordList) { - VariantContextGenes variantContextGenes = vepMapper.getGenes(vcfRecord, knownGenes); - knownGenes.putAll(variantContextGenes.getGenes()); - for (Gene gene : variantContextGenes.getGenes().values()) { + VcfRecordGenes vcfRecordGenes = vcfRecord.getVcfRecordGenes(knownGenes); + knownGenes.putAll(vcfRecordGenes.getGenes()); + for (Gene gene : vcfRecordGenes.getGenes().values()) { List geneVariantList; if (geneVariantMap.containsKey(gene.getId())) { geneVariantList = geneVariantMap.get(gene.getId()); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java index 22456b1..22e904f 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java @@ -2,13 +2,9 @@ import static java.util.Objects.requireNonNull; -import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFFileReader; import htsjdk.variant.vcf.VCFHeader; -import java.util.Collections; -import java.util.List; import java.util.Set; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -19,36 +15,28 @@ public class VcfReader implements AutoCloseable { private final VCFFileReader vcfFileReader; - private final VepMapper vepMapper; + private final VepMetadata vepMetadata; private final Set pathogenicClasses; - public VcfReader(VCFFileReader vcfFileReader, VepMapper vepMapper, Set pathogenicClasses) { + public VcfReader(VCFFileReader vcfFileReader, VepMetadata vepMetadata, Set pathogenicClasses) { this.vcfFileReader = requireNonNull(vcfFileReader); - this.vepMapper = vepMapper; + this.vepMetadata = vepMetadata; this.pathogenicClasses = pathogenicClasses; } public Stream stream() { //FIXME - return StreamSupport.stream(vcfFileReader.spliterator(), false).map(vc -> new VcfRecord(vc, getPathogenicAlleles(vc))); - } - - private List getPathogenicAlleles(VariantContext vc) { - if(pathogenicClasses.isEmpty()){ - return vc.getAlternateAlleles(); - } - //FIXME - return Collections.emptyList(); + return StreamSupport.stream(vcfFileReader.spliterator(), false).map(vc -> new VcfRecord(vc, vepMetadata, pathogenicClasses)); } public Stream filteredStream(Set classes) { //FIXME: filter on classes - return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, getPathogenicAlleles(vc))); + return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, vepMetadata, pathogenicClasses)); } public Stream filteredStream(Set classes, String geneId) { //FIXME: filter on classes and geneId - return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, getPathogenicAlleles(vc))); + return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, vepMetadata, pathogenicClasses)); } @Override diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java index 51521b8..a5fd711 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java @@ -19,6 +19,6 @@ public VcfReaderFactoryImpl(VepMetadataServiceFactoryImpl vepMetadataServiceFact public VcfReader create(Settings settings) { Path inputVcfPath = settings.getInputVcfPath(); VCFFileReader vcfFileReader = new VCFFileReader(inputVcfPath.toFile(), false); - return new VcfReader(vcfFileReader, new VepMapper(vcfFileReader.getFileHeader(), vepMetadataServiceFactoryImpl.create()), settings.getPathogenicClasses()); + return new VcfReader(vcfFileReader, new VepMetadata(vcfFileReader.getFileHeader(), vepMetadataServiceFactoryImpl.create()), settings.getPathogenicClasses()); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java index 4c45c86..8f24891 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java @@ -2,18 +2,27 @@ import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.VariantContext; +import lombok.Getter; +import org.molgenis.vcf.inheritance.matcher.model.Gene; +import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; +import org.molgenis.vcf.inheritance.matcher.model.VcfRecordGenes; -import java.util.List; +import java.util.*; +import static java.util.Collections.emptyMap; import static java.util.Objects.requireNonNull; public class VcfRecord { - VariantContext variantContext; - private final List pathogenicAlleles; + private final VariantContext variantContext; + @Getter + private final VepMetadata vepMetadata; + @Getter + private final Set pathogenicClasses; - public VcfRecord(VariantContext variantContext, List pathogenicAlleles) { + public VcfRecord(VariantContext variantContext, VepMetadata vepMetadata, Set pathogenicClasses) { this.variantContext = requireNonNull(variantContext); - this.pathogenicAlleles = requireNonNull(pathogenicAlleles); + this.vepMetadata = requireNonNull(vepMetadata); + this.pathogenicClasses = requireNonNull(pathogenicClasses); } public EffectiveGenotype getGenotype(String sampleId){ @@ -21,7 +30,14 @@ public EffectiveGenotype getGenotype(String sampleId){ if(gt == null){ return null; } - return new EffectiveGenotype(gt, variantContext, pathogenicAlleles); + return new EffectiveGenotype(gt, variantContext, getPathogenicAlleles()); + } + + private List getPathogenicAlleles() { + if(pathogenicClasses.isEmpty()){ + return variantContext.getAlternateAlleles(); + } + return null; } public List getAttributeAsStringList(String vepFieldId) { @@ -47,4 +63,69 @@ public int getStart() { public Allele getReference() { return variantContext.getReference(); } + + + public VcfRecordGenes getVcfRecordGenes() { + return getVcfRecordGenes(emptyMap()); + } + + public VcfRecordGenes getVcfRecordGenes(Map knownGenes) { + VcfRecordGenes.VcfRecordGenesBuilder genesBuilder = VcfRecordGenes.builder(); + Map genes = new HashMap<>(); + List vepValues = getAttributeAsStringList(vepMetadata.getVepFieldId()); + for (String vepValue : vepValues) { + String[] vepSplit = vepValue.split("\\|", -1); + String gene = vepSplit[vepMetadata.getGeneIndex()]; + String source = vepSplit[vepMetadata.getGeneSourceIndex()]; + if (gene.isEmpty() || source.isEmpty()) { + genesBuilder.containsVcWithoutGene(true); + continue; + } + + if (!knownGenes.containsKey(gene)) { + Set modes = new HashSet<>(); + if (vepMetadata.getInheritanceIndex() != -1) { + String[] inheritanceModes + = vepSplit[vepMetadata.getInheritanceIndex()].split("&"); + mapGeneInheritance(modes, inheritanceModes); + } + genes.put(gene, new Gene(gene, source, modes)); + } else { + genes.put(gene, knownGenes.get(gene)); + } + } + genesBuilder.genes(genes); + return genesBuilder.build(); + } + + public Set getClassesForAllele(int alleleIndex){ + List vepValues = getAttributeAsStringList(vepMetadata.getVepFieldId()); + Set classes = new HashSet<>(); + for (String vepValue : vepValues) { + String[] vepSplit = vepValue.split("\\|", -1); + int csqAlleleIndex = Integer.parseInt(vepSplit[vepMetadata.getAlleleNumIndex()]); + if(csqAlleleIndex == alleleIndex){ + classes.add(vepSplit[vepMetadata.getClassIndex()]); + } + } + return classes; + } + + private void mapGeneInheritance(Set modes, String[] inheritanceModes) { + for (String mode : inheritanceModes) { + switch (mode) { + case "AR" -> modes.add(InheritanceMode.AR); + case "AD" -> modes.add(InheritanceMode.AD); + case "XLR" -> modes.add(InheritanceMode.XLR); + case "XLD" -> modes.add(InheritanceMode.XLD); + case "XL" -> { + modes.add(InheritanceMode.XLR); + modes.add(InheritanceMode.XLD); + } + default -> { + //We ignore all the modes that are not used for matching. + } + } + } + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java deleted file mode 100644 index 452fa31..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMapper.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import static java.util.Collections.emptyMap; - -import htsjdk.variant.vcf.VCFHeader; -import htsjdk.variant.vcf.VCFInfoHeaderLine; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.molgenis.vcf.inheritance.matcher.model.Gene; -import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; -import org.molgenis.vcf.inheritance.matcher.model.VariantContextGenes; -import org.molgenis.vcf.utils.metadata.FieldMetadataService; -import org.molgenis.vcf.utils.model.FieldMetadata; -import org.molgenis.vcf.utils.model.NestedField; - -public class VepMapper { - - public static final String GENE = "Gene"; - public static final String ALLELE_NUM = "ALLELE_NUM"; - public static final String VIP_CLASS = "VIPC"; - public static final String SYMBOL_SOURCE = "SYMBOL_SOURCE"; - private static final String INFO_DESCRIPTION_PREFIX = - "Consequence annotations from Ensembl VEP. Format: "; - private static final String INHERITANCE = "InheritanceModesGene"; - private String vepFieldId = null; - private final VCFHeader vcfHeader; - private final FieldMetadataService fieldMetadataService; - private int geneIndex = -1; - private int geneSourceIndex = -1; - private int inheritanceIndex = -1; - private int alleleNumIndex = -1; - private int classIndex = -1; - - public VepMapper(VCFHeader vcfHeader, FieldMetadataService fieldMetadataService) { - this.vcfHeader = vcfHeader; - this.fieldMetadataService = fieldMetadataService; - - init(); - } - - private static boolean canMap(VCFInfoHeaderLine vcfInfoHeaderLine) { - // match on the description since the INFO ID is configurable (default: CSQ) - String description = vcfInfoHeaderLine.getDescription(); - return description.startsWith(INFO_DESCRIPTION_PREFIX); - } - - private void init() { - for (VCFInfoHeaderLine vcfInfoHeaderLine : vcfHeader.getInfoHeaderLines()) { - if (canMap(vcfInfoHeaderLine)) { - this.vepFieldId = vcfInfoHeaderLine.getID(); - FieldMetadata fieldMetadata = fieldMetadataService.load( - vcfInfoHeaderLine); - Map nestedFields = fieldMetadata.getNestedFields(); - geneIndex = nestedFields.get(GENE) != null ? nestedFields.get(GENE).getIndex():-1; - geneSourceIndex = nestedFields.get(SYMBOL_SOURCE) != null ? nestedFields.get(SYMBOL_SOURCE).getIndex():-1; - inheritanceIndex = nestedFields.get(INHERITANCE) != null ? nestedFields.get(INHERITANCE).getIndex():-1; - alleleNumIndex = nestedFields.get(ALLELE_NUM) != null ? nestedFields.get(ALLELE_NUM).getIndex():-1; - classIndex = nestedFields.get(VIP_CLASS) != null ? nestedFields.get(VIP_CLASS).getIndex():-1; - return; - } - } - throw new MissingInfoException("VEP"); - } - - public VariantContextGenes getGenes(VcfRecord record) { - return getGenes(record, emptyMap()); - } - - public VariantContextGenes getGenes(VcfRecord record, Map knownGenes) { - VariantContextGenes.VariantContextGenesBuilder genesBuilder = VariantContextGenes.builder(); - Map genes = new HashMap<>(); - List vepValues = record.getAttributeAsStringList(vepFieldId); - for (String vepValue : vepValues) { - String[] vepSplit = vepValue.split("\\|", -1); - String gene = vepSplit[geneIndex]; - String source = vepSplit[geneSourceIndex]; - if (gene.isEmpty() || source.isEmpty()) { - genesBuilder.containsVcWithoutGene(true); - continue; - } - - if (!knownGenes.containsKey(gene)) { - Set modes = new HashSet<>(); - if (inheritanceIndex != -1) { - String[] inheritanceModes - = vepSplit[inheritanceIndex].split("&"); - mapGeneInheritance(modes, inheritanceModes); - } - genes.put(gene, new Gene(gene, source, modes)); - } else { - genes.put(gene, knownGenes.get(gene)); - } - } - genesBuilder.genes(genes); - return genesBuilder.build(); - } - - public Set getClassesForAllele(VcfRecord record, int alleleIndex){ - List vepValues = record.getAttributeAsStringList(vepFieldId); - Set classes = new HashSet<>(); - for (String vepValue : vepValues) { - String[] vepSplit = vepValue.split("\\|", -1); - int csqAlleleIndex = Integer.parseInt(vepSplit[alleleNumIndex]); - if(csqAlleleIndex == alleleIndex){ - classes.add(vepSplit[classIndex]); - } - } - return classes; - } - - private void mapGeneInheritance(Set modes, String[] inheritanceModes) { - for (String mode : inheritanceModes) { - switch (mode) { - case "AR" -> modes.add(InheritanceMode.AR); - case "AD" -> modes.add(InheritanceMode.AD); - case "XLR" -> modes.add(InheritanceMode.XLR); - case "XLD" -> modes.add(InheritanceMode.XLD); - case "XL" -> { - modes.add(InheritanceMode.XLR); - modes.add(InheritanceMode.XLD); - } - default -> { - //We ignore all the modes that are not used for matching. - } - } - } - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java new file mode 100644 index 0000000..baf049b --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java @@ -0,0 +1,76 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.vcf.VCFHeader; +import htsjdk.variant.vcf.VCFInfoHeaderLine; +import java.util.Map; + +import lombok.Getter; +import org.molgenis.vcf.utils.metadata.FieldMetadataService; +import org.molgenis.vcf.utils.model.FieldMetadata; +import org.molgenis.vcf.utils.model.NestedField; + +public class VepMetadata { + + public static final String GENE = "Gene"; + public static final String ALLELE_NUM = "ALLELE_NUM"; + public static final String VIP_CLASS = "VIPC"; + public static final String SYMBOL_SOURCE = "SYMBOL_SOURCE"; + private static final String INFO_DESCRIPTION_PREFIX = + "Consequence annotations from Ensembl VEP. Format: "; + private static final String INHERITANCE = "InheritanceModesGene"; + private VCFHeader vcfHeader = null; + private FieldMetadataService fieldMetadataService = null; + @Getter + private String vepFieldId = null; + @Getter + private int geneIndex = -1; + @Getter + private int geneSourceIndex = -1; + @Getter + private int inheritanceIndex = -1; + @Getter + private int alleleNumIndex = -1; + @Getter + private int classIndex = -1; + + public VepMetadata(VCFHeader vcfHeader, FieldMetadataService fieldMetadataService) { + this.vcfHeader = vcfHeader; + this.fieldMetadataService = fieldMetadataService; + + init(); + } + + private static boolean canMap(VCFInfoHeaderLine vcfInfoHeaderLine) { + // match on the description since the INFO ID is configurable (default: CSQ) + String description = vcfInfoHeaderLine.getDescription(); + return description.startsWith(INFO_DESCRIPTION_PREFIX); + } + + private void init() { + for (VCFInfoHeaderLine vcfInfoHeaderLine : vcfHeader.getInfoHeaderLines()) { + if (canMap(vcfInfoHeaderLine)) { + this.vepFieldId = vcfInfoHeaderLine.getID(); + FieldMetadata fieldMetadata = fieldMetadataService.load( + vcfInfoHeaderLine); + Map nestedFields = fieldMetadata.getNestedFields(); + geneIndex = nestedFields.get(GENE) != null ? nestedFields.get(GENE).getIndex():-1; + geneSourceIndex = nestedFields.get(SYMBOL_SOURCE) != null ? nestedFields.get(SYMBOL_SOURCE).getIndex():-1; + inheritanceIndex = nestedFields.get(INHERITANCE) != null ? nestedFields.get(INHERITANCE).getIndex():-1; + alleleNumIndex = nestedFields.get(ALLELE_NUM) != null ? nestedFields.get(ALLELE_NUM).getIndex():-1; + classIndex = nestedFields.get(VIP_CLASS) != null ? nestedFields.get(VIP_CLASS).getIndex():-1; + return; + } + } + throw new MissingInfoException("VEP"); + } + + //For testing purposes + public VepMetadata(String vepFieldId, int geneIndex, int geneSourceIndex, int inheritanceIndex, int alleleNumIndex, int classIndex) { + this.vepFieldId = vepFieldId; + this.geneIndex = geneIndex; + this.geneSourceIndex = geneSourceIndex; + this.inheritanceIndex = inheritanceIndex; + this.alleleNumIndex = alleleNumIndex; + this.classIndex = classIndex; + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index 2d73b87..ee28361 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -11,7 +11,7 @@ import htsjdk.variant.variantcontext.GenotypeBuilder; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMapper; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; import org.molgenis.vcf.inheritance.matcher.model.Gene; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -20,10 +20,10 @@ public class ArCompoundChecker { - private final VepMapper vepMapper; + private final VepMetadata vepMetadata; - public ArCompoundChecker(VepMapper vepMapper) { - this.vepMapper = vepMapper; + public ArCompoundChecker(VepMetadata vepMetadata) { + this.vepMetadata = vepMetadata; } public List check( @@ -31,7 +31,7 @@ public List check( VcfRecord vcfRecord, Pedigree family, MatchEnum isAr) { if (onAutosome(vcfRecord) && isAr != TRUE) { List compounds = new ArrayList<>(); - Map genes = vepMapper.getGenes(vcfRecord).getGenes(); + Map genes = vcfRecord.getVcfRecordGenes().getGenes(); for (Gene gene : genes.values()) { checkForGene(geneVariantMap, vcfRecord, family, compounds, gene); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VariantContextGenes.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java similarity index 80% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/model/VariantContextGenes.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java index 297eb5d..3b0f24d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VariantContextGenes.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java @@ -5,8 +5,9 @@ import java.util.Map; @Data @Builder -public class VariantContextGenes{ +public class VcfRecordGenes { Map genes; + //FIXME: is this used? @Builder.Default boolean containsVcWithoutGene = false; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java index cf51338..41446f9 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java @@ -1,9 +1,9 @@ package org.molgenis.vcf.inheritance.matcher.util; import org.molgenis.vcf.inheritance.matcher.InheritanceService; -import org.molgenis.vcf.inheritance.matcher.VepMapper; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.Settings; public interface InheritanceServiceFactory { - InheritanceService create(Settings settings, VepMapper vepMapper); + InheritanceService create(Settings settings, VepMetadata vepMetadata); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java index e46eb8d..c69a162 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java @@ -20,7 +20,7 @@ public InheritanceServiceFactoryImpl(Annotator annotator, PedigreeInheritanceChe } @Override - public InheritanceService create(Settings settings, VepMapper vepMapper) { - return new InheritanceService(annotator, vepMapper, pedigreeInheritanceChecker, settings.getInputPedPaths(), settings.getProbands()); + public InheritanceService create(Settings settings, VepMetadata vepMetadata) { + return new InheritanceService(annotator, vepMetadata, pedigreeInheritanceChecker, settings.getInputPedPaths(), settings.getProbands()); } } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java index 7e5494a..0e0bf68 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java @@ -31,6 +31,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.model.Annotation; import org.molgenis.vcf.inheritance.matcher.model.Inheritance; @@ -44,6 +45,9 @@ class AnnotatorTest { private Annotator annotator; + @Mock + VepMetadata vepMetadata; + @BeforeEach void setUp() { annotator = new Annotator(); @@ -151,7 +155,7 @@ void annotateInheritance() { Set.of("GENE1", "GENE2")).build(); Map annotationMap = Map.of("Patient", annotation); - VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, emptyList()), families, annotationMap).unwrap(); + VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, vepMetadata, emptySet()), families, annotationMap).unwrap(); assertAll( () -> assertEquals("AD_IP,AR_C", @@ -182,7 +186,7 @@ void annotateInheritanceMissingGeneInheritancePattern() { Annotation annotation = Annotation.builder().inheritance(inheritance).build(); Map annotationMap = Map.of("Patient", annotation); - VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, emptyList()), families, annotationMap).unwrap(); + VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, vepMetadata, emptySet()), families, annotationMap).unwrap(); assertAll( () -> assertEquals("AD_IP,AR_C", @@ -211,7 +215,7 @@ void annotateInheritanceNoMatch() { Annotation annotation = Annotation.builder().inheritance(inheritance).build(); Map annotationMap = Map.of("Patient", annotation); - VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, emptyList()), families, annotationMap).unwrap(); + VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, vepMetadata, emptySet()), families, annotationMap).unwrap(); assertAll( () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MODES)), diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java index 074c2d0..95fe2e8 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java @@ -20,7 +20,7 @@ void matchInheritanceMatch() { Set.of(new PedigreeInheritanceMatch(AR,false))).compounds(singleton("OTHER_VARIANT")).build(); Map inheritanceMap = Map.of("sample1", inheritance1, "sample2", inheritance2); - VariantContextGenes genes = VariantContextGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", Set.of(AR,AD)), "GENE2", new Gene("GENE2","EntrezGene", Set.of(AD)))).build(); + VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", Set.of(AR,AD)), "GENE2", new Gene("GENE2","EntrezGene", Set.of(AD)))).build(); Map actual = InheritanceMatcher .matchInheritance(inheritanceMap, genes); @@ -38,7 +38,7 @@ void matchInheritanceMatch() { void matchInheritanceMismatch() { Inheritance inheritance = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false))).build(); Map inheritanceMap = Map.of("sample1", inheritance); - VariantContextGenes genes = VariantContextGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", Set.of(AR)))).build(); + VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", Set.of(AR)))).build(); Map actual = InheritanceMatcher .matchInheritance(inheritanceMap, genes); @@ -56,7 +56,7 @@ void matchInheritanceNoSuitableModes() { Inheritance inheritance1 = Inheritance.builder().match(FALSE).pedigreeInheritanceMatches( emptySet()).pedigreeInheritanceMatches(emptySet()).build(); Map inheritanceMap = Map.of("sample1", inheritance1); - VariantContextGenes genes = VariantContextGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", Set.of(AR,AD)),"GENE2",new Gene("GENE2","EntrezGene", Set.of(AD)))).build(); + VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", Set.of(AR,AD)),"GENE2",new Gene("GENE2","EntrezGene", Set.of(AD)))).build(); Map actual = InheritanceMatcher .matchInheritance(inheritanceMap, genes); @@ -72,7 +72,7 @@ void matchInheritanceNoSuitableModes() { void matchInheritanceUnknownGene() { Inheritance inheritance1 = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false), new PedigreeInheritanceMatch(InheritanceMode.AR_C,false))).compounds(singleton("OTHER_VARIANT")).build(); Map inheritanceMap = Map.of("sample1", inheritance1); - VariantContextGenes genes = VariantContextGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", emptySet()))).build(); + VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", emptySet()))).build(); Map actual = InheritanceMatcher .matchInheritance(inheritanceMap, genes); @@ -88,7 +88,7 @@ void matchInheritanceUnknownGeneAndKnownGeneMatch() { Inheritance inheritance1 = Inheritance.builder().pedigreeInheritanceMatches( Set.of(new PedigreeInheritanceMatch(AR_C, false))).compounds(singleton("OTHER_VARIANT")).build(); Map inheritanceMap = Map.of("sample1", inheritance1); - VariantContextGenes genes = VariantContextGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", emptySet()),"GENE2",new Gene("GENE2","EntrezGene", Set.of(AR)))).build(); + VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", emptySet()),"GENE2",new Gene("GENE2","EntrezGene", Set.of(AR)))).build(); Map actual = InheritanceMatcher .matchInheritance(inheritanceMap, genes); @@ -105,7 +105,7 @@ void matchInheritanceUnknownGeneAndKnownGeneMismatch() { Set.of(new PedigreeInheritanceMatch(AD,false))).compounds(emptySet()).build(); Map inheritanceMap = Map.of("sample1", inheritance1); - VariantContextGenes genes = VariantContextGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", emptySet()),"GENE2", + VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", emptySet()),"GENE2", new Gene("GENE2","EntrezGene", Set.of(AR)))).build(); Map actual = InheritanceMatcher diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java index 189e45c..f2ad31c 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java @@ -44,6 +44,9 @@ class PedigreeInheritanceCheckerTest { MtChecker mtChecker; @Mock DeNovoChecker deNovoChecker; + @Mock + VepMetadata vepMetadata; + private PedigreeInheritanceChecker pedigreeInheritanceChecker; @BeforeEach @@ -54,7 +57,7 @@ void setUp() { @Test void testAdIpPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); @@ -78,7 +81,7 @@ void testAdIpPotential() { @Test void testXlRDTrue() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); @@ -104,7 +107,7 @@ void testXlRDTrue() { @Test void testArAdMixed() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); @@ -128,7 +131,7 @@ void testArAdMixed() { @Test void testAdDenovoMixed() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); @@ -152,7 +155,7 @@ void testAdDenovoMixed() { @Test void testArPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); VariantContext vc2 = mock(VariantContext.class); Allele ref = mock(Allele.class); when(ref.getBaseString()).thenReturn("A"); @@ -162,7 +165,7 @@ void testArPotential() { when(vc2.getStart()).thenReturn(123); when(vc2.getReference()).thenReturn(ref); when(vc2.getAlternateAlleles()).thenReturn(List.of(alt)); - VcfRecord record2 = new VcfRecord(vc2, emptyList()); + VcfRecord record2 = new VcfRecord(vc2, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); @@ -186,7 +189,7 @@ void testArPotential() { @Test void testMtPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); @@ -210,7 +213,7 @@ void testMtPotential() { @Test void testYl() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, emptyList()); + VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); Pedigree family = mock(Pedigree.class); Sample sample = mock(Sample.class); ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java similarity index 88% rename from src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java rename to src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java index bf79854..67c9546 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMapperTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java @@ -1,6 +1,5 @@ package org.molgenis.vcf.inheritance.matcher; -import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -27,21 +26,21 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.model.Gene; -import org.molgenis.vcf.inheritance.matcher.model.VariantContextGenes; +import org.molgenis.vcf.inheritance.matcher.model.VcfRecordGenes; import org.molgenis.vcf.utils.metadata.FieldMetadataService; import org.molgenis.vcf.utils.model.FieldMetadata; import org.molgenis.vcf.utils.model.NestedField; import org.molgenis.vcf.utils.model.NumberType; @ExtendWith(MockitoExtension.class) -class VepMapperTest { +class VepMetadataTest { @Mock VariantContext vc; @Mock FieldMetadataService fieldMetadataService; - private VepMapper vepMapper; + private VepMetadata vepMetadata; @BeforeEach void setUp() { @@ -72,7 +71,7 @@ void setUp() { when(fieldMetadataService.load(infoHeader)).thenReturn( FieldMetadata.builder().nestedFields(vepMeta).build()); when(header.getInfoHeaderLines()).thenReturn(Collections.singletonList(infoHeader)); - vepMapper = new VepMapper(header, fieldMetadataService); + vepMetadata = new VepMetadata(header, fieldMetadataService); } @Test @@ -82,11 +81,12 @@ void getGenes() { "T|missense_variant|MODERATE|TEST2|ENSG00000123457|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XL&ICI|Leber_congenital_amaurosis_9:AR|", "T|missense_variant|MODERATE|TEST2|ENSG00000123458|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XLR&XLD|Leber_congenital_amaurosis_9:AR|")); - VariantContextGenes expected = VariantContextGenes.builder() + VcfRecordGenes expected = VcfRecordGenes.builder() .genes(Map.of("ENSG00000123457", new Gene("ENSG00000123457","HGNC", Set.of(XLD, XLR)), "ENSG00000123456", new Gene("ENSG00000123456","HGNC", Set.of(AD, AR)), "ENSG00000123458", new Gene("ENSG00000123458","HGNC", Set.of(XLD, XLR)))).build(); - assertEquals(expected, vepMapper.getGenes(new VcfRecord(vc, emptyList()))); + VcfRecord vcfRecord = new VcfRecord(vc, vepMetadata, emptySet()); + assertEquals(expected, vcfRecord.getVcfRecordGenes()); } @Test @@ -97,10 +97,11 @@ void getGenesEmptyValues() { "T|missense_variant|MODERATE||ENSG00000123457|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XL&ICI|Leber_congenital_amaurosis_9:AR|", "T|missense_variant|MODERATE|||Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XLR&XLD|Leber_congenital_amaurosis_9:AR|")); - VariantContextGenes expected = VariantContextGenes.builder().containsVcWithoutGene(true).genes(Map + VcfRecordGenes expected = VcfRecordGenes.builder().containsVcWithoutGene(true).genes(Map .of("ENSG00000123457", new Gene("ENSG00000123457", "HGNC", Set.of(XLD, XLR)), "ENSG00000123456", new Gene("ENSG00000123456", "HGNC", Set.of(AD, AR)))).build(); - assertEquals(expected, vepMapper.getGenes(new VcfRecord(vc2, emptyList()))); + VcfRecord vcfRecord = new VcfRecord(vc2, vepMetadata, emptySet()); + assertEquals(expected, vcfRecord.getVcfRecordGenes()); } @Test @@ -108,7 +109,7 @@ void getGenesEmptySymbolSource() { VariantContext variantContext = mock(VariantContext.class); when(variantContext.getAttributeAsStringList(eq("CSQ"), any())).thenReturn(List.of( "G|missense_variant|MODERATE|TEST1|ENSG00000123456|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>G|ENSP00000366410.1:p.Arg207Gly|763|619|207|R/G|Cgg/Ggg|||1|||17877||AD&AR|Leber_congenital_amaurosis_9:AR|")); - - assertEquals(VariantContextGenes.builder().genes(Map.of()).containsVcWithoutGene(true).build(), vepMapper.getGenes(new VcfRecord(variantContext, emptyList()))); + VcfRecord vcfRecord = new VcfRecord(variantContext, vepMetadata, emptySet()); + assertEquals(VcfRecordGenes.builder().genes(Map.of()).containsVcWithoutGene(true).build(), vcfRecord.getVcfRecordGenes()); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java index 199226d..327b932 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java @@ -1,6 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.createGenotype; import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; @@ -17,8 +18,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -73,7 +76,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - ""), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),""), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java index 06097c4..9a089c6 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java @@ -23,8 +23,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -36,6 +38,9 @@ class AdNonPenCheckerTest { private final AdNonPenetranceChecker adNonPenetranceChecker = new AdNonPenetranceChecker(); + @Mock + VepMetadata vepMetadata; + @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") void check(VcfRecord vcfRecord, Pedigree family, String expectedString, @@ -48,7 +53,7 @@ void check(VcfRecord vcfRecord, Pedigree family, String expectedString, void testCheckAd() { VariantContext variantContext = mock(VariantContext.class); Pedigree family = mock(Pedigree.class); - assertEquals(FALSE, adNonPenetranceChecker.check(new VcfRecord(variantContext, emptyList()), family, MatchEnum.TRUE)); + assertEquals(FALSE, adNonPenetranceChecker.check(new VcfRecord(variantContext, vepMetadata, emptySet()), family, MatchEnum.TRUE)); } private static Stream provideTestCases() throws IOException { @@ -86,7 +91,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - ""), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),""), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java index 282ae83..27403c7 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -73,7 +74,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - ""), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),""), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java index 270b701..f65b813 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java @@ -11,7 +11,7 @@ import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; + import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -27,7 +27,7 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMapper; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -39,7 +39,7 @@ class ArCompoundCheckerTest { @Mock - private VepMapper vepMapper; + private VepMetadata vepMetadata; private final static Gene gene1 = new Gene("GENE1", "EntrezGene", singleton(InheritanceMode.AR)); @ParameterizedTest(name = "{index} {4}") @@ -48,8 +48,7 @@ void check(VcfRecord vcfRecord, Map> geneVariantMap, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - ArCompoundChecker arCompoundChecker = new ArCompoundChecker(vepMapper); - when(vepMapper.getGenes(vcfRecord)).thenReturn(VariantContextGenes.builder().genes(singletonMap("GENE1", gene1)).build()); + ArCompoundChecker arCompoundChecker = new ArCompoundChecker(vepMetadata); List compounds = arCompoundChecker.check(geneVariantMap, vcfRecord, family, FALSE); if(expected == FALSE) { assertTrue(compounds.isEmpty()); @@ -118,10 +117,10 @@ private static Stream provideTestCases() throws IOException { return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - ""), + new VepMetadata("CSQ",0,1,-1,-1,-1),"GENE1|Entrez"), singletonMap("GENE1", singletonList(VariantContextTestUtil .createVariantContext(otherGenotypes, - ""))), family, expected, testName); + new VepMetadata("CSQ",0,1,-1,-1,-1),"GENE1|Entrez"))), family, expected, testName); }); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java index b78edc7..847f081 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java @@ -16,6 +16,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -57,7 +58,7 @@ private static Stream provideTestCases() throws IOException { .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), createGenotype("Father", fatherGt), createGenotype("Mother", motherGt)), - "", chrom), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1), "", chrom), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java index 49cca07..282bbd2 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -75,7 +76,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - "", "chrM"), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),"", "chrM"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java index a0e91b9..1532bf6 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -71,7 +72,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - "", "chrX"), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),"", "chrX"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java index ffbf4b1..144b5e4 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -71,7 +72,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - "", "X"), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),"", "X"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java index 2bab9c4..67ab698 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -75,7 +76,7 @@ private static Stream provideTestCases() throws IOException { } return Arguments.of(VariantContextTestUtil .createVariantContext(genotypes, - "", "chrY"), family, expected, testName); + new VepMetadata("CSQ",-1,-1,-1,-1,-1),"","chrY"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java index 008f041..d0a49ba 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java @@ -15,7 +15,7 @@ class InheritanceServiceFactoryImplTest { @Mock private Annotator annotator; @Mock - private VepMapper vepMapper; + private VepMetadata vepMetadata; @Mock private PedigreeInheritanceChecker pedigreeInheritanceChecker; @@ -26,7 +26,7 @@ void setUp() { } @Test void create() { - InheritanceService inheritanceServiceFactory = inheritanceServiceFactoryImpl.create(Settings.builder().build(), vepMapper); + InheritanceService inheritanceServiceFactory = inheritanceServiceFactoryImpl.create(Settings.builder().build(), vepMetadata); assertNotNull(inheritanceServiceFactory); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java index ca8702e..9eb5239 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java @@ -3,9 +3,9 @@ import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.Genotype; import htsjdk.variant.variantcontext.GenotypeBuilder; -import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.variantcontext.VariantContextBuilder; import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import java.util.ArrayList; @@ -21,11 +21,11 @@ public class VariantContextTestUtil { public static final Allele REF = Allele.REF_T; public static final Allele ALT = Allele.ALT_A; - public static VcfRecord createVariantContext(List genotypes, String vep) { - return createVariantContext(genotypes, vep, "1"); + public static VcfRecord createVariantContext(List genotypes, VepMetadata vepMetadata, String VepData) { + return createVariantContext(genotypes, vepMetadata, VepData, "1"); } - public static VcfRecord createVariantContext(List genotypes, String vep, + public static VcfRecord createVariantContext(List genotypes, VepMetadata vepMetadata, String VepData, String contig) { VariantContextBuilder builder = new VariantContextBuilder(); builder.chr(contig); @@ -33,8 +33,8 @@ public static VcfRecord createVariantContext(List genotypes, String ve builder.stop(12345); builder.alleles(Arrays.asList(REF, ALT)); builder.genotypes(genotypes); - builder.attribute("CSQ", vep); - return new VcfRecord(builder.make(), emptyList()); + builder.attribute("CSQ", VepData); + return new VcfRecord(builder.make(), vepMetadata, emptySet()); } public static Genotype createGenotype(String sample, String gt) { From 2aaf941ecc166707acd1ad33bac5019866ec1c65 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 5 Sep 2024 17:09:12 +0200 Subject: [PATCH 05/28] WIP --- .../vcf/inheritance/matcher/EffectiveGenotype.java | 9 ++++++--- .../molgenis/vcf/inheritance/matcher/VcfRecord.java | 12 ++++++++++-- .../org/molgenis/vcf/inheritance/matcher/AppIT.java | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java index 0b57961..2545ab9 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java @@ -73,7 +73,8 @@ public boolean isCalled() { } public boolean isHom() { - return effectiveGenotype.isHom(); + //for inheritance matching consider any ALT/ALT combination HOM_ALT + return effectiveGenotype.isHom() || this.isHomAlt(); } public boolean hasAltAllele() { @@ -85,7 +86,8 @@ public List getAlleles() { } public boolean isHet() { - return effectiveGenotype.isHet(); + //for inheritance matching consider any ALT/ALT combination HOM_ALT + return effectiveGenotype.isHet() && effectiveGenotype.hasRefAllele(); } public boolean isPhased() { @@ -93,7 +95,8 @@ public boolean isPhased() { } public boolean isHomAlt() { - return effectiveGenotype.isHomVar(); + //for inheritance matching consider any ALT/ALT combination HOM_ALT + return effectiveGenotype.isCalled() && !effectiveGenotype.isMixed() && !effectiveGenotype.hasRefAllele(); } public Allele getAllele(int i) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java index 8f24891..0eafdaf 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java @@ -34,10 +34,18 @@ public EffectiveGenotype getGenotype(String sampleId){ } private List getPathogenicAlleles() { + List pathogenicAlleles = new ArrayList(); if(pathogenicClasses.isEmpty()){ - return variantContext.getAlternateAlleles(); + pathogenicAlleles = variantContext.getAlternateAlleles(); + }else { + for (int i = 1; i <= variantContext.getAlternateAlleles().size(); i++) { + Allele allele = variantContext.getAlleles().get(i); + if(getClassesForAllele(i).stream().anyMatch(pathogenicClasses::contains)) { + pathogenicAlleles.add(allele); + } + } } - return null; + return pathogenicAlleles; } public List getAttributeAsStringList(String vepFieldId) { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java index 0664570..e968003 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java @@ -54,7 +54,7 @@ void testProband() throws IOException { String pedigree = ResourceUtils.getFile("classpath:pedigree_complex.ped").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-pc","LP,P"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); From 41420af881a4c1c330d36990c1e4be12549d79f2 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Mon, 23 Sep 2024 13:10:28 +0200 Subject: [PATCH 06/28] WIP --- .gitignore | 2 +- README.md | 46 ++-- .../vcf/inheritance/matcher/Annotator.java | 191 +++++++-------- .../matcher/AppCommandLineOptions.java | 2 +- .../matcher/AppCommandLineRunner.java | 12 +- .../matcher/AppRunnerFactoryImpl.java | 9 +- .../matcher/EffectiveGenotype.java | 95 +++----- .../matcher/InheritanceMatcher.java | 98 -------- .../matcher/InheritanceService.java | 212 ++++++++-------- .../matcher/PedigreeInheritanceChecker.java | 101 ++------ .../vcf/inheritance/matcher/RecordWriter.java | 5 +- .../inheritance/matcher/RecordWriterImpl.java | 6 +- .../matcher/VariantContextUtils.java | 36 ++- .../matcher/VariantGeneRecord.java | 56 +++++ .../inheritance/matcher/VariantRecord.java | 20 ++ .../vcf/inheritance/matcher/VcfReader.java | 23 +- .../matcher/VcfReaderFactoryImpl.java | 3 +- .../vcf/inheritance/matcher/VcfRecord.java | 139 ----------- .../inheritance/matcher/VcfRecordFactory.java | 9 + .../matcher/VcfRecordFactoryImpl.java | 101 ++++++++ .../vcf/inheritance/matcher/VepMetadata.java | 14 +- .../matcher/checker/AdChecker.java | 123 ++++++---- .../checker/AdNonPenetranceChecker.java | 24 +- .../matcher/checker/ArChecker.java | 133 ++++++---- .../matcher/checker/ArCompoundChecker.java | 213 ++++++++-------- .../matcher/checker/DeNovoChecker.java | 33 ++- .../matcher/checker/HaploidChecker.java | 87 ------- .../matcher/checker/InheritanceChecker.java | 10 +- .../matcher/checker/MtChecker.java | 102 +++++++- .../matcher/checker/XlChecker.java | 28 +-- .../matcher/checker/XldChecker.java | 111 ++++++--- .../matcher/checker/XlrChecker.java | 118 +++++---- .../matcher/checker/YlChecker.java | 119 +++++++-- .../inheritance/matcher/model/Annotation.java | 17 -- .../matcher/model/CompoundCheckResult.java | 5 +- .../vcf/inheritance/matcher/model/Gene.java | 12 - .../inheritance/matcher/model/GeneInfo.java | 6 + .../matcher/model/Inheritance.java | 25 -- .../matcher/model/InheritanceGeneResult.java | 81 +++++++ .../matcher/model/InheritanceResult.java | 16 ++ .../model/PedigreeInheritanceMatch.java | 7 +- .../matcher/model/VcfRecordGenes.java | 2 +- .../util/InheritanceServiceFactory.java | 3 +- .../util/InheritanceServiceFactoryImpl.java | 4 +- .../matcher/util/InheritanceUtils.java | 4 - .../inheritance/matcher/AnnotatorTest.java | 228 ------------------ .../vcf/inheritance/matcher/AppIT.java | 2 +- .../matcher/InheritanceMatcherTest.java | 120 --------- .../PedigreeInheritanceCheckerTest.java | 191 +++------------ .../matcher/VariantContextUtilsTest.java | 3 +- .../inheritance/matcher/VepMetadataTest.java | 115 --------- .../matcher/checker/AdCheckerTest.java | 17 +- .../matcher/checker/AdNonPenCheckerTest.java | 23 +- .../matcher/checker/ArCheckerTest.java | 15 +- .../checker/ArCompoundCheckerTest.java | 165 ++++++------- .../matcher/checker/DeNovoCheckerTest.java | 25 +- .../matcher/checker/MtCheckerTest.java | 14 +- .../matcher/checker/PedigreeTestUtil.java | 17 -- .../matcher/checker/XldCheckerTest.java | 15 +- .../matcher/checker/XlrCheckerTest.java | 15 +- .../matcher/checker/YlCheckerTest.java | 14 +- ...eritanceResultServiceFactoryImplTest.java} | 6 +- .../matcher/util/VariantContextTestUtil.java | 128 +++++----- src/test/resources/ADtests.tsv | 5 +- src/test/resources/ArCompoundTests.tsv | 8 +- src/test/resources/XldTests.tsv | 4 +- src/test/resources/YLtests.tsv | 10 +- src/test/resources/expected_noParents.vcf | 36 +-- src/test/resources/expected_noPed.vcf | 36 +-- .../resources/expected_noVEPinheritance.vcf | 20 +- src/test/resources/expected_probands.vcf | 36 +-- src/test/resources/integration.vcf | 30 +-- 72 files changed, 1591 insertions(+), 2170 deletions(-) delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/Annotation.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/Gene.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/Inheritance.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java delete mode 100644 src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java delete mode 100644 src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java delete mode 100644 src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java rename src/test/java/org/molgenis/vcf/inheritance/matcher/util/{InheritanceServiceFactoryImplTest.java => InheritanceResultServiceFactoryImplTest.java} (85%) diff --git a/.gitignore b/.gitignore index 5fe2080..7bc438e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ hs_err_pid* /.idea/ /target/ -/vip-inheritance-matcher.iml +/vip-inheritanceResult-matcher.iml diff --git a/README.md b/README.md index eec8fd7..96d2b67 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ Possible inheritance modes are calculated on the following rules: - Unaffected samples cannot have both variants. ##### For phased data: - Affected samples need to have both variants on different alleles. -- Unaffected samples cannot have both variants on different alleles, however they can have both variants on the same alleles.. +- Unaffected samples cannot have both variants on different alleles, however they can have both variants on the same alleles. #### AD: - Affected samples have to carry the ALT allele. Unaffected samples have to be homozygous REF. @@ -121,33 +121,33 @@ For variants on the X chromosome deploid genotypes are assumed to be female, sin ### Running without VEP inheritance mode annotations If the VEP inheritance mode annotation is missing the tool still calculates all possible inheritance modes. -However the actual matching on genes will obviously never yield a result. +However, the actual matching on genes will obviously never yield a result. ### Compatible Inheritance modes The VIP inheritance plugin adds a whole range of inheritance modes, however for matching purposes we can only use a subset: AD,AR,XL,XLD,XLR. #### Supported -|OMIM Inheritance*|Annotation| -|---|---| -|X-LINKED DOMINANT|XD| -|X-LINKED RECESSIVE|XR| -|X-LINKED*|XL| -|AUTOSOMAL RECESSIVE|AR| -|AUTOSOMAL DOMINANT|AD| +| OMIM Inheritance* | Annotation | +|---------------------|------------| +| X-LINKED DOMINANT | XD | +| X-LINKED RECESSIVE | XR | +| X-LINKED* | XL | +| AUTOSOMAL RECESSIVE | AR | +| AUTOSOMAL DOMINANT | AD | *: Please note that XL is matched by both XD and XR. #### Unsupported -|OMIM Inheritance*|Annotation| -|---|---| -|Y-LINKED|YL| -|PSEUDOAUTOSOMAL RECESSIVE|PR| -|PSEUDOAUTOSOMAL DOMINANT|PD| -|ISOLATED CASES|IC| -|DIGENIC|DG| -|DIGENIC RECESSIVE|DGR| -|DIGENIC DOMINANT|DGD| -|MITOCHONDRIAL|MT| -|MULTIFACTORIAL|MF| -|SOMATIC MUTATION|SM| -|SOMATIC MOSAICISM|SMM| -|INHERITED CHROMOSOMAL IMBALANCE|ICI| +| OMIM Inheritance* | Annotation | +|---------------------------------|------------| +| Y-LINKED | YL | +| PSEUDOAUTOSOMAL RECESSIVE | PR | +| PSEUDOAUTOSOMAL DOMINANT | PD | +| ISOLATED CASES | IC | +| DIGENIC | DG | +| DIGENIC RECESSIVE | DGR | +| DIGENIC DOMINANT | DGD | +| MITOCHONDRIAL | MT | +| MULTIFACTORIAL | MF | +| SOMATIC MUTATION | SM | +| SOMATIC MOSAICISM | SMM | +| INHERITED CHROMOSOMAL IMBALANCE | ICI | diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 509729d..0027658 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -1,15 +1,11 @@ package org.molgenis.vcf.inheritance.matcher; -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.TRUE; -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.POTENTIAL; +import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.utils.utils.HeaderUtils.fixVcfFilterHeaderLines; import static org.molgenis.vcf.utils.utils.HeaderUtils.fixVcfFormatHeaderLines; import static org.molgenis.vcf.utils.utils.HeaderUtils.fixVcfInfoHeaderLines; -import htsjdk.variant.variantcontext.GenotypeBuilder; -import htsjdk.variant.variantcontext.GenotypesContext; -import htsjdk.variant.variantcontext.VariantContext; -import htsjdk.variant.variantcontext.VariantContextBuilder; +import htsjdk.variant.variantcontext.*; import htsjdk.variant.vcf.VCFFormatHeaderLine; import htsjdk.variant.vcf.VCFHeader; import htsjdk.variant.vcf.VCFHeaderLine; @@ -17,7 +13,6 @@ import htsjdk.variant.vcf.VCFHeaderLineType; import java.util.*; -import java.util.Map.Entry; import java.util.stream.Collectors; import org.molgenis.vcf.inheritance.matcher.model.*; @@ -29,113 +24,99 @@ @Component public class Annotator { - public static final String INHERITANCE_MODES = "VI"; - public static final String POSSIBLE_COMPOUND = "VIC"; - public static final String DENOVO = "VID"; - public static final String INHERITANCE_MATCH = "VIM"; - public static final String MATCHING_GENES = "VIG"; - - VCFHeader annotateHeader(VCFHeader vcfHeader) { - vcfHeader - .addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MODES, VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "An enumeration of possible inheritance modes based on the pedigree of the sample. Potential values: AD, AD_IP, AR, AR_C, XLR, XLD")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(POSSIBLE_COMPOUND, 1, - VCFHeaderLineType.String, - "Possible Compound hetrozygote variants.")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(DENOVO, 1, - VCFHeaderLineType.Integer, - "De novo variant.")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MATCH, 1, - VCFHeaderLineType.Integer, - "Inheritance Match: Genotypes, affected statuses and known gene inheritance patterns match.")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(MATCHING_GENES, VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "Genes with a (potential) inheritance match.")); - - Set headerLines = new LinkedHashSet<>(); - //workaround for "Escaped doublequotes in INFO descriptions result in invalid VCF file" - // https://github.com/samtools/htsjdk/issues/1661 - headerLines.addAll(fixVcfInfoHeaderLines( - vcfHeader)); - headerLines.addAll(fixVcfFormatHeaderLines( - vcfHeader)); - headerLines.addAll(fixVcfFilterHeaderLines(vcfHeader)); - headerLines.addAll(vcfHeader.getOtherHeaderLines()); - headerLines.addAll(vcfHeader.getContigLines()); - - vcfHeader = new VCFHeader(headerLines, vcfHeader.getGenotypeSamples()); - return vcfHeader; - } + public static final String INHERITANCE_MODES = "VI"; + public static final String POSSIBLE_COMPOUND = "VIC"; + public static final String DENOVO = "VID"; + public static final String INHERITANCE_MATCH = "VIM"; + public static final String MATCHING_GENES = "VIG"; + + VCFHeader annotateHeader(VCFHeader vcfHeader) { + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MODES, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "An enumeration of possible inheritance modes based on the pedigree of the sample. Potential values: AD, AD_IP, AR, AR_C, XLR, XLD")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(POSSIBLE_COMPOUND, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Possible Compound hetrozygote variants.")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(DENOVO, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.Integer, "De novo variant.")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MATCH, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.Integer, "Inheritance Match: Genotypes, affected statuses and known gene inheritance patterns match.")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(MATCHING_GENES, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Genes with a (potential) inheritance match.")); + + Set headerLines = new LinkedHashSet<>(); + //workaround for "Escaped doublequotes in INFO descriptions result in invalid VCF file" + // https://github.com/samtools/htsjdk/issues/1661 + headerLines.addAll(fixVcfInfoHeaderLines(vcfHeader)); + headerLines.addAll(fixVcfFormatHeaderLines(vcfHeader)); + headerLines.addAll(fixVcfFilterHeaderLines(vcfHeader)); + headerLines.addAll(vcfHeader.getOtherHeaderLines()); + headerLines.addAll(vcfHeader.getContigLines()); + + vcfHeader = new VCFHeader(headerLines, vcfHeader.getGenotypeSamples()); + return vcfHeader; + } - VcfRecord annotateInheritance(VcfRecord vcfRecord, Map familyMap, - Map annotationMap) { - GenotypesContext genotypesContext = GenotypesContext.copy(vcfRecord.unwrap().getGenotypes()); - VariantContextBuilder variantContextBuilder = new VariantContextBuilder(vcfRecord.unwrap()); - for (Entry sampleFamilyEntry : familyMap.entrySet()) { - for (Sample sample : sampleFamilyEntry.getValue().getMembers().values()) { - String sampleId = sample.getPerson().getIndividualId(); - if (annotationMap.containsKey(sampleId)) { - annotateGenotype(vcfRecord, annotationMap.get(sampleId), genotypesContext, sample); + VariantContext annotateInheritance(VariantRecord variantRecord, Collection pedigrees, Map inheritanceResultMap, List probands) { + GenotypesContext genotypesContext = GenotypesContext.copy(variantRecord.variantContext().getGenotypes()); + VariantContextBuilder variantContextBuilder = new VariantContextBuilder(variantRecord.variantContext()); + for (Pedigree pedigree : pedigrees) { + pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(sample -> { + Genotype genotype = variantRecord.getGenotype(sample.getPerson().getIndividualId()); + if (inheritanceResultMap.containsKey(pedigree) && genotype != null) { + genotypesContext.replace(annotateGenotype(inheritanceResultMap.get(pedigree), genotype, sample)); + } + }); } - } + return variantContextBuilder.genotypes(genotypesContext).make(); } - return new VcfRecord(variantContextBuilder.genotypes(genotypesContext).make(), vcfRecord.getVepMetadata(), vcfRecord.getPathogenicClasses()); - } - - private void annotateGenotype(VcfRecord vcfRecord, Annotation annotation, - GenotypesContext genotypesContext, Sample sample) { - if (vcfRecord.getGenotype(sample.getPerson().getIndividualId()) != null) { - GenotypeBuilder genotypeBuilder = new GenotypeBuilder( - vcfRecord.getGenotype(sample.getPerson().getIndividualId()).unwrap()); - String inheritanceModes = String - .join(",", mapInheritanceModes(annotation.getInheritance())); - if (!inheritanceModes.isEmpty()) { - genotypeBuilder.attribute(INHERITANCE_MODES, inheritanceModes); - } - String compounds = annotation.getInheritance().getCompounds().isEmpty() ? null : String - .join(",", annotation.getInheritance().getCompounds()); - genotypeBuilder.attribute(POSSIBLE_COMPOUND, compounds); - genotypeBuilder.attribute(DENOVO, mapDenovoValue(annotation)); - MatchEnum match = annotation.getInheritance().getMatch(); - String inheritanceMatch = mapInheritanceMatch(match); - genotypeBuilder - .attribute(INHERITANCE_MATCH, inheritanceMatch); - if ((match == TRUE || match == POTENTIAL) && annotation.getMatchingGenes() != null && !annotation.getMatchingGenes().isEmpty()) { - genotypeBuilder - .attribute(MATCHING_GENES, annotation.getMatchingGenes().stream().sorted().collect( - Collectors.joining(","))); - } - genotypesContext.replace(genotypeBuilder.make()); + private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype genotype, Sample sample) { + GenotypeBuilder genotypeBuilder = new GenotypeBuilder(genotype); + List VIM = new ArrayList<>(); + List VIC = new ArrayList<>(); + List VIG = new ArrayList<>(); + List VI = new ArrayList<>(); + for (InheritanceGeneResult inheritanceGeneResult : inheritanceResult.getInheritanceGeneResults()) { + String compounds = inheritanceGeneResult.getCompounds().isEmpty() ? "" : String.join("&", inheritanceGeneResult.getCompounds().stream().map(this::createKey).toList()); + MatchEnum match = inheritanceGeneResult.getMatch(); + VI.add(String.join("&", mapInheritanceModes(inheritanceGeneResult))); + VIM.add(mapInheritanceMatch(match)); + VIC.add(compounds); + if ((match == TRUE || match == POTENTIAL)) { + VIG.add(inheritanceGeneResult.getGeneInfo().geneId()); + } + } + genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", VI)); + genotypeBuilder.attribute(INHERITANCE_MATCH, String.join(",", VIM)); + genotypeBuilder.attribute(POSSIBLE_COMPOUND, String.join(",", VIC)); + genotypeBuilder.attribute(MATCHING_GENES, String.join(",", VIG)); + genotypeBuilder.attribute(DENOVO, mapDenovoValue(inheritanceResult, sample)); + return genotypeBuilder.make(); } - } - private static String mapDenovoValue(Annotation annotation) { - return switch (annotation.getInheritance().getDenovo()){ - case TRUE -> "1"; - case FALSE -> "0"; - case POTENTIAL -> null; - }; - } + private static String mapDenovoValue(InheritanceResult inheritanceResult, Sample sample) { + return switch (inheritanceResult.getDenovo().get(sample)) { + case TRUE -> "1"; + case FALSE -> "0"; + case POTENTIAL -> ""; + }; + } - private static String mapInheritanceMatch(MatchEnum match) { - String inheritanceMatch; - switch (match){ - case TRUE -> inheritanceMatch = "1"; - case FALSE -> inheritanceMatch = "0"; - case POTENTIAL -> inheritanceMatch = null; - default -> throw new UnexpectedEnumException(match); + private static String mapInheritanceMatch(MatchEnum match) { + String inheritanceMatch; + switch (match) { + case TRUE -> inheritanceMatch = "1"; + case FALSE -> inheritanceMatch = "0"; + case POTENTIAL -> inheritanceMatch = ""; + default -> throw new UnexpectedEnumException(match); + } + return inheritanceMatch; } - return inheritanceMatch; - } - private Set mapInheritanceModes(Inheritance inheritance) { - Set result = new HashSet<>(); - for (PedigreeInheritanceMatch pedigreeInheritanceMatch : inheritance.getPedigreeInheritanceMatches()) { - result.add(pedigreeInheritanceMatch.getInheritanceMode().name()); + private Set mapInheritanceModes(InheritanceGeneResult inheritanceResult) { + Set result = new HashSet<>(); + for (PedigreeInheritanceMatch pedigreeInheritanceMatch : inheritanceResult.getPedigreeInheritanceMatches()) { + result.add(pedigreeInheritanceMatch.inheritanceMode().name()); + } + return result; } - return result; - } + private String createKey(CompoundCheckResult result) { + VariantGeneRecord record = result.getPossibleCompound(); + return String.format("%s_%s_%s_%s", record.getContig(), record.getStart(), record.getReference().getBaseString(), record.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java index bb3e951..a460fb0 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java @@ -60,7 +60,7 @@ class AppCommandLineOptions { Option.builder(OPT_CLASSES) .hasArg(true) .longOpt(OPT_CLASSES_LONG) - .desc("Comma-separated list of classes to be treated as pathogenic in the inheritance matcher") + .desc("Mapping of VIP class to pathogenicity, format: P:LP,P;V:VUS;B:LB,b") .build()); appOptions.addOption( Option.builder(OPT_FORCE) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java index e7e0ea3..6e00b8f 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java @@ -10,10 +10,7 @@ import org.springframework.stereotype.Component; import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; import static java.util.Objects.requireNonNull; import static org.molgenis.vcf.inheritance.matcher.AppCommandLineOptions.*; @@ -96,7 +93,7 @@ private Settings mapSettings(CommandLine commandLine) { Set pathogenicClasses; if (commandLine.hasOption(OPT_CLASSES)) { - pathogenicClasses = Set.of(commandLine.getOptionValue(OPT_CLASSES).split(",")); + pathogenicClasses = mapPathogenicityClasses(commandLine.getOptionValue(OPT_CLASSES)); } else { pathogenicClasses = Set.of(); } @@ -118,6 +115,11 @@ private Settings mapSettings(CommandLine commandLine) { .build(); } + //TODO: validate + private Set mapPathogenicityClasses(String optionValue) { + return Set.of(optionValue.split(",")); + } + private CommandLine getCommandLine(String[] args) { CommandLine commandLine = null; try { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java index 01b46ff..fcf3302 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java @@ -2,7 +2,6 @@ import org.molgenis.vcf.inheritance.matcher.model.Settings; import org.molgenis.vcf.inheritance.matcher.util.InheritanceServiceFactory; -import org.molgenis.vcf.inheritance.matcher.util.VepMetadataServiceFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -17,17 +16,14 @@ class AppRunnerFactoryImpl implements AppRunnerFactory { private final VcfReaderFactory vcfReaderFactory; private final RecordWriterFactory recordWriterFactory; private final InheritanceServiceFactory inheritanceServiceFactory; - private final VepMetadataServiceFactory vepMetadataServiceFactory; AppRunnerFactoryImpl( VcfReaderFactory vcfReaderFactory, RecordWriterFactory recordWriterFactory, - InheritanceServiceFactory inheritanceServiceFactory, - VepMetadataServiceFactory vepMetadataServiceFactory) { + InheritanceServiceFactory inheritanceServiceFactory) { this.vcfReaderFactory = requireNonNull(vcfReaderFactory); this.recordWriterFactory = requireNonNull(recordWriterFactory); this.inheritanceServiceFactory = inheritanceServiceFactory; - this.vepMetadataServiceFactory = vepMetadataServiceFactory; } // Suppress 'Resources should be closed' @@ -35,10 +31,9 @@ class AppRunnerFactoryImpl implements AppRunnerFactory { @Override public AppRunner create(Settings settings) { VcfReader vcfReader = vcfReaderFactory.create(settings); - VepMetadata vepMetadata = new VepMetadata(vcfReader.getFileHeader(), vepMetadataServiceFactory.create()); try { RecordWriter recordWriter = recordWriterFactory.create(settings); - return new AppRunnerImpl(vcfReader, recordWriter, inheritanceServiceFactory.create(settings, vepMetadata)); + return new AppRunnerImpl(vcfReader, recordWriter, inheritanceServiceFactory.create(settings)); } catch (Exception e) { try { vcfReader.close(); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java index 2545ab9..8506d5a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java @@ -1,105 +1,68 @@ package org.molgenis.vcf.inheritance.matcher; import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.GenotypeBuilder; -import htsjdk.variant.variantcontext.VariantContext; import java.util.List; import static java.util.Objects.requireNonNull; public class EffectiveGenotype { - htsjdk.variant.variantcontext.Genotype originalGenotype; - private final VariantContext variantContext; - private final List pathogenicAlleles; - private Genotype effectiveGenotype; + final htsjdk.variant.variantcontext.Genotype genotype; - public EffectiveGenotype(htsjdk.variant.variantcontext.Genotype originalGenotype, VariantContext variantContext, List pathogenicAlleles) { - this.originalGenotype = requireNonNull(originalGenotype); - this.variantContext = requireNonNull(variantContext); - this.pathogenicAlleles = requireNonNull(pathogenicAlleles); - - init(); + public EffectiveGenotype(htsjdk.variant.variantcontext.Genotype originalGenotype) { + this.genotype = requireNonNull(originalGenotype); } public htsjdk.variant.variantcontext.Genotype unwrap() { - return originalGenotype; - } - - //Consider Benign allele as a REF allele - private void init() { - if (originalGenotype.isNoCall()) { - effectiveGenotype = originalGenotype; - } - GenotypeBuilder genotypeBuilder = new GenotypeBuilder(originalGenotype); - genotypeBuilder.alleles(originalGenotype.getAlleles().stream().map(this::mapAllele).toList()); - effectiveGenotype = genotypeBuilder.make(); - } - - private Allele mapAllele(Allele allele) { - if (isPathogenic(allele) || allele.isNoCall()) { - return allele; - } - return variantContext.getReference(); - } - - private boolean isPathogenic(Allele allele) { - //if no pathogenic classes are provided consider all ALTs pathogenic - if (allele.isNonReference() && pathogenicAlleles.isEmpty()) { - return true; - } - return pathogenicAlleles.contains(allele); + return genotype; } - public boolean isHomRef() { - return effectiveGenotype.isHomRef(); + //combination of no_call/call or fully called gt with single VUS allele + public boolean isMixed() { + return genotype.isMixed() || (!genotype.isHom()); } - public boolean isNoCall() { - return effectiveGenotype.isNoCall(); + public int getPloidy() { + return genotype.getPloidy(); } - public boolean isMixed() { - return effectiveGenotype.isMixed(); + public boolean isCalled() { + return genotype.isCalled(); } - public int getPloidy() { - return effectiveGenotype.getPloidy(); + public List getAlleles() { + return genotype.getAlleles(); } - public boolean isCalled() { - return effectiveGenotype.isCalled(); + public boolean isPhased() { + return genotype.isPhased(); } - public boolean isHom() { - //for inheritance matching consider any ALT/ALT combination HOM_ALT - return effectiveGenotype.isHom() || this.isHomAlt(); + public Allele getAllele(int i) { + return genotype.getAllele(i); } - public boolean hasAltAllele() { - return effectiveGenotype.hasAltAllele(); + public boolean isHomRef() { + return genotype.isHomRef(); } - public List getAlleles() { - return effectiveGenotype.getAlleles(); + public boolean isNoCall() { + return genotype.isNoCall(); } - public boolean isHet() { - //for inheritance matching consider any ALT/ALT combination HOM_ALT - return effectiveGenotype.isHet() && effectiveGenotype.hasRefAllele(); + public boolean hasMissingAllele() { + return genotype.getAlleles().stream().anyMatch(Allele::isNoCall); } - public boolean isPhased() { - return effectiveGenotype.isPhased(); + public boolean hasReference() { + return genotype.getAlleles().stream().anyMatch(Allele::isReference); } - public boolean isHomAlt() { - //for inheritance matching consider any ALT/ALT combination HOM_ALT - return effectiveGenotype.isCalled() && !effectiveGenotype.isMixed() && !effectiveGenotype.hasRefAllele(); + public boolean hasAlt() { + return genotype.getAlleles().stream().anyMatch(allele -> allele.isNonReference() && allele.isCalled()); } - public Allele getAllele(int i) { - return effectiveGenotype.getAllele(i); + public boolean isHom() { + return genotype.isHom(); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java deleted file mode 100644 index 745d144..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcher.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.molgenis.vcf.inheritance.matcher.model.*; -import org.molgenis.vcf.utils.UnexpectedEnumException; - -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; - -public class InheritanceMatcher { - - private InheritanceMatcher() { - } - - public static Map matchInheritance( - Map inheritanceMap, VcfRecordGenes genes) { - Map sampleAnnotationMap = new HashMap<>(); - for (Entry entry : inheritanceMap.entrySet()) { - Set matchingGenes = new HashSet<>(); - String sample = entry.getKey(); - Inheritance inheritance = entry.getValue(); - //If no inheritance pattern is suitable for the sample, regardless of the gene: inheritance match is false. - if(inheritance.getPedigreeInheritanceMatches().isEmpty()){ - inheritance.setMatch(FALSE); - } - else { - matchGeneInheritance(genes, matchingGenes, inheritance); - } - Annotation annotation = Annotation.builder().matchingGenes(matchingGenes) - .inheritance(inheritance).build(); - sampleAnnotationMap.put(sample, annotation); - } - return sampleAnnotationMap; - } - - /** - * If there are one or more matches between sample inheritance modes and gene inheritance modes: - * - inheritance match is true - * If there are no matches between sample inheritance modes and gene inheritance modes: - * - inheritance match is unknown if any genes for the variant have unknown inheritance pattern. - * - inheritance match is false if all genes for the variant have known (but mismatching) inheritance pattern. - */ - private static void matchGeneInheritance(VcfRecordGenes genes, Set matchingGenes, Inheritance pedigreeInheritance) { - boolean containsUnknownGene = false; - for (Gene gene : genes.getGenes().values()) { - Set geneInheritanceModes = gene - .getInheritanceModes(); - if( geneInheritanceModes.isEmpty() ){ - containsUnknownGene = true; - } - if (geneInheritanceModes.stream() - .anyMatch(geneInheritanceMode -> isMatch(pedigreeInheritance.getPedigreeInheritanceMatches(), geneInheritanceMode))) { - matchingGenes.add(gene.getId()); - if(pedigreeInheritance.getPedigreeInheritanceMatches().stream().anyMatch(pedigreeInheritanceMatch -> !pedigreeInheritanceMatch.isUncertain())){ - pedigreeInheritance.setMatch(TRUE); - }else { - pedigreeInheritance.setMatch(POTENTIAL); - } - } - } - if(matchingGenes.isEmpty()) { - if (containsUnknownGene || genes.isContainsVcWithoutGene()) { - pedigreeInheritance.setMatch(POTENTIAL); - } else { - pedigreeInheritance.setMatch(FALSE); - } - } - } - - private static Boolean isMatch(Set pedigreeInheritanceMatches, InheritanceMode geneInheritanceMode) { - for(PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { - switch (pedigreeInheritanceMatch.getInheritanceMode()) { - case AD, AD_IP -> { - if (geneInheritanceMode == AD) { - return true; - } - } - case AR, AR_C -> { - if (geneInheritanceMode == AR) { - return true; - } - } - case XLR, XLD -> { - if (geneInheritanceMode == XL) { - return true; - } - } - default -> throw new UnexpectedEnumException(pedigreeInheritanceMatch.getInheritanceMode()); - } - } - return false; - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index 70d7d00..d023476 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -1,133 +1,135 @@ package org.molgenis.vcf.inheritance.matcher; +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFHeader; import org.molgenis.vcf.inheritance.matcher.checker.ArCompoundChecker; +import org.molgenis.vcf.inheritance.matcher.checker.DeNovoChecker; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.utils.sample.model.*; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import static java.util.Collections.singletonMap; import static java.util.Objects.requireNonNull; -import static org.molgenis.vcf.inheritance.matcher.InheritanceMatcher.matchInheritance; +import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.getAltAlleles; +import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; +import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.FALSE; +import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.POTENTIAL; import static org.molgenis.vcf.utils.sample.mapper.PedToSamplesMapper.mapPedFileToPedigrees; public class InheritanceService { + private final Annotator annotator; + private final PedigreeInheritanceChecker pedigreeInheritanceChecker; + private final List pedigreePaths; + private final List probands; + private final DeNovoChecker deNovoChecker = new DeNovoChecker(); + private final ArCompoundChecker arCompoundChecker = new ArCompoundChecker(); + + public InheritanceService( + Annotator annotator, PedigreeInheritanceChecker pedigreeInheritanceChecker, List pedigreePaths, List probands) { + this.annotator = requireNonNull(annotator); + this.pedigreeInheritanceChecker = requireNonNull(pedigreeInheritanceChecker); + this.pedigreePaths = pedigreePaths; + this.probands = probands; + } - private final Annotator annotator; - private final List pedigreePaths; - private final List probands; - private final VepMetadata vepMetadata; - private ArCompoundChecker arCompoundChecker; - private final PedigreeInheritanceChecker pedigreeInheritanceChecker; - - public InheritanceService( - Annotator annotator, VepMetadata vepMetadata, PedigreeInheritanceChecker pedigreeInheritanceChecker, List pedigreePaths, List probands) { - this.annotator = requireNonNull(annotator); - this.vepMetadata = requireNonNull(vepMetadata); - this.pedigreeInheritanceChecker = requireNonNull(pedigreeInheritanceChecker); - - this.pedigreePaths = pedigreePaths; - this.probands = probands; - } - - public void run(VcfReader vcfReader, RecordWriter recordWriter) { - this.arCompoundChecker = new ArCompoundChecker(vepMetadata); + public void run(VcfReader vcfReader, RecordWriter recordWriter) { - Map knownGenes = new HashMap<>(); - Map familyList; - if (!pedigreePaths.isEmpty()) { - familyList = mapPedFileToPedigrees(pedigreePaths); - } else { - familyList = createFamilyFromVcf(vcfReader.getFileHeader()); - } - VCFHeader newHeader = annotator.annotateHeader(vcfReader.getFileHeader()); - recordWriter.writeHeader(newHeader); + Collection pedigrees; + if (!pedigreePaths.isEmpty()) { + pedigrees = mapPedFileToPedigrees(pedigreePaths).values(); + } else { + pedigrees = createFamilyFromVcf(vcfReader.getFileHeader()); + } - List vcfRecordList = new ArrayList<>(); - vcfReader.stream().forEach(vcfRecordList::add); - Map> geneVariantMap = createGeneVariantMap(vepMetadata, knownGenes, - vcfRecordList); - vcfRecordList.stream().filter(record -> !record.getAlternateAlleles().isEmpty()).map( - vcfRecord -> processSingleVariantcontext(probands, vepMetadata, familyList, - geneVariantMap, vcfRecord)).forEach(recordWriter::add); + VCFHeader newHeader = annotator.annotateHeader(vcfReader.getFileHeader()); + recordWriter.writeHeader(newHeader); - } + Map> vcfRecordGeneInfoMap = new HashMap<>(); + List variantRecords = vcfReader.stream().toList(); - private VcfRecord processSingleVariantcontext(List probands, VepMetadata vepMetadata, - Map pedigreeList, - Map> geneVariantMap, VcfRecord vcfRecord) { - Map inheritanceMap = matchInheritanceForVariant(geneVariantMap, - vcfRecord, pedigreeList, probands); - Map annotationMap = matchInheritance(inheritanceMap, - vcfRecord.getVcfRecordGenes()); - return annotator.annotateInheritance(vcfRecord, pedigreeList, annotationMap); - } + for (VariantRecord variantRecord : variantRecords) { + variantRecord.variantGeneRecords().values().forEach(variantGeneRecord -> { + //Only perform matching if a pathogenic or vus allele is present + if (!variantGeneRecord.getGeneInfo().geneId().isEmpty() && !variantGeneRecord.getPathogenicAlleles().isEmpty()) { + addToVcfRecordMap(variantGeneRecord, vcfRecordGeneInfoMap); + } + }); + } - private Map> createGeneVariantMap(VepMetadata vepMetadata, - Map knownGenes, - List vcfRecordList) { - Map> geneVariantMap = new HashMap<>(); - for (VcfRecord vcfRecord : vcfRecordList) { - VcfRecordGenes vcfRecordGenes = vcfRecord.getVcfRecordGenes(knownGenes); - knownGenes.putAll(vcfRecordGenes.getGenes()); - for (Gene gene : vcfRecordGenes.getGenes().values()) { - List geneVariantList; - if (geneVariantMap.containsKey(gene.getId())) { - geneVariantList = geneVariantMap.get(gene.getId()); - } else { - geneVariantList = new ArrayList<>(); + for (VariantRecord variantRecord : variantRecords) { + Map inheritanceResultMap = new HashMap<>(); + for (Pedigree pedigree : pedigrees) { + Map geneInheritanceResults = new HashMap<>(); + for (VariantGeneRecord variantGeneRecord : variantRecord.variantGeneRecords().values().stream().toList()) {//FIXME stream directly + InheritanceGeneResult geneInheritanceResult = InheritanceGeneResult.builder().geneInfo(variantGeneRecord.getGeneInfo()).build(); + Set altAllelesForPedigree = getAltAlleles(variantGeneRecord, pedigree); + //Only perform matching if a family member with a pathogenic allele is present + if (altAllelesForPedigree.stream().anyMatch(allele -> variantGeneRecord.getPathogenicAlleles().contains(allele))) { + addToVcfRecordMap(variantGeneRecord, vcfRecordGeneInfoMap); + Set modes = Set.of(AD, AR, XLD, XLR, MT, YL); + modes.forEach(mode -> { + MatchEnum isMatch = pedigreeInheritanceChecker.check(variantGeneRecord, pedigree, mode); + if (isMatch != FALSE) { + geneInheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(mode, isMatch == POTENTIAL)); + } + }); + if (geneInheritanceResult.getPedigreeInheritanceMatches().stream().noneMatch(match -> match.inheritanceMode() == AD)) { + MatchEnum isAdIpMatch = pedigreeInheritanceChecker.check(variantGeneRecord, pedigree, AD_IP); + if (isAdIpMatch != FALSE) { + geneInheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(AD_IP, isAdIpMatch == POTENTIAL)); + } + } + } + if(!variantGeneRecord.getGeneInfo().geneId().isEmpty()) { + Set compounds = arCompoundChecker.check(vcfRecordGeneInfoMap, variantGeneRecord, pedigree); + if (!compounds.isEmpty()) { + geneInheritanceResult.setCompounds(compounds); + boolean isCertain = compounds.stream().anyMatch(CompoundCheckResult::isCertain); + Set pedigreeInheritanceMatches = geneInheritanceResult.getPedigreeInheritanceMatches(); + pedigreeInheritanceMatches.add(new PedigreeInheritanceMatch(AR_C, !isCertain)); + geneInheritanceResult.setPedigreeInheritanceMatches(pedigreeInheritanceMatches); + geneInheritanceResults.put(variantGeneRecord.getGeneInfo(), geneInheritanceResult); + } + } + geneInheritanceResults.put(variantGeneRecord.getGeneInfo(), geneInheritanceResult); + } + Map denovoResult = new HashMap<>(); + pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> + denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); + InheritanceResult inheritanceResult = InheritanceResult.builder().build(); + inheritanceResult.setInheritanceGeneResults(geneInheritanceResults.values()); + inheritanceResult.setDenovo(denovoResult); + inheritanceResultMap.put(pedigree, inheritanceResult); + } + + VariantContext annotatedVc = annotator.annotateInheritance(variantRecord, pedigrees, inheritanceResultMap, probands); + recordWriter.add(annotatedVc); } - geneVariantList.add(vcfRecord); - geneVariantMap.put(gene.getId(), geneVariantList); - } } - return geneVariantMap; - } - private Map createFamilyFromVcf(VCFHeader fileHeader) { - Map familyList = new HashMap<>(); - ArrayList sampleNames = fileHeader.getSampleNamesInOrder(); - for (String sampleName : sampleNames) { - //no ped: unknown Sex, assume affected, no relatives, therefor the sampleId can be used as familyId - Person person = Person.builder().familyId(sampleName).individualId(sampleName) - .paternalId("") - .maternalId("").sex(Sex.UNKNOWN) - .affectedStatus(AffectedStatus.AFFECTED).build(); - Sample sample = Sample.builder().person(person).proband(true).build(); - familyList.put(sampleName, Pedigree.builder() - .id(sampleName).members(singletonMap(sampleName, sample)).build()); + private void addToVcfRecordMap(VariantGeneRecord variantGeneRecord, Map> vcfRecordGeneInfoMap) { + GeneInfo geneInfo = variantGeneRecord.getGeneInfo(); + Set records = vcfRecordGeneInfoMap.containsKey(geneInfo) ? vcfRecordGeneInfoMap.get(geneInfo) : new HashSet<>(); + records.add(variantGeneRecord); + vcfRecordGeneInfoMap.put(geneInfo, records); } - return familyList; - } - private Map matchInheritanceForVariant( - Map> geneVariantMap, - VcfRecord record, Map familyList, - List probands) { - Map result = new HashMap<>(); - for (Pedigree family : familyList.values()) { - for (Sample sample : family.getMembers().values()) { - if (probands.contains(sample.getPerson().getIndividualId()) || (probands.isEmpty() - && sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED)) { - result.put(sample.getPerson().getIndividualId(), - calculateInheritanceForFamily(geneVariantMap, record, family, - sample)); + private Set createFamilyFromVcf(VCFHeader fileHeader) { + Set familyList = new HashSet<>(); + ArrayList sampleNames = fileHeader.getSampleNamesInOrder(); + for (String sampleName : sampleNames) { + //no ped: unknown Sex, assume affected, no relatives, therefor the sampleId can be used as familyId + Person person = Person.builder().familyId(sampleName).individualId(sampleName) + .paternalId("") + .maternalId("").sex(Sex.UNKNOWN) + .affectedStatus(AffectedStatus.AFFECTED).build(); + Sample sample = Sample.builder().person(person).proband(true).build(); + familyList.add(Pedigree.builder() + .id(sampleName).members(singletonMap(sampleName, sample)).build()); } - } + return familyList; } - return result; - } - - private Inheritance calculateInheritanceForFamily( - Map> geneVariantMap, - VcfRecord record, Pedigree family, - Sample sample) { - return pedigreeInheritanceChecker.calculatePedigreeInheritance(geneVariantMap, record, sample, family, arCompoundChecker); - } - } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java index ff4abc5..b00829a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java @@ -1,18 +1,11 @@ package org.molgenis.vcf.inheritance.matcher; -import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.checker.*; import org.molgenis.vcf.inheritance.matcher.model.*; +import org.molgenis.vcf.utils.UnexpectedEnumException; import org.molgenis.vcf.utils.sample.model.Pedigree; -import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; - @Component public class PedigreeInheritanceChecker { private final XldChecker xldChecker; @@ -23,9 +16,8 @@ public class PedigreeInheritanceChecker { private final ArChecker arChecker; private final MtChecker mtChecker; private final YlChecker ylChecker; - private final DeNovoChecker deNovoChecker; - public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, AdChecker adChecker, AdNonPenetranceChecker adNonPenetranceChecker, ArChecker arChecker, YlChecker ylChecker, MtChecker mtChecker, DeNovoChecker deNovoChecker) { + public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, AdChecker adChecker, AdNonPenetranceChecker adNonPenetranceChecker, ArChecker arChecker, YlChecker ylChecker, MtChecker mtChecker) { this.xldChecker = xldChecker; this.xlrChecker = xlrChecker; this.adChecker = adChecker; @@ -33,85 +25,20 @@ public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, this.arChecker = arChecker; this.mtChecker = mtChecker; this.ylChecker = ylChecker; - this.deNovoChecker = deNovoChecker; - } - - //TODO replace geneVariantMap with context incl pathogenic classes - Inheritance calculatePedigreeInheritance( - Map> geneVariantMap, VcfRecord record, Sample sample, Pedigree filteredFamily, ArCompoundChecker arCompoundChecker) { - Inheritance inheritance = Inheritance.builder().build(); - //FIXME - checkAr(geneVariantMap, record, filteredFamily, inheritance, arCompoundChecker); - checkAd(record, filteredFamily, inheritance); - checkXl(record, filteredFamily, inheritance); - checkMt(record, filteredFamily, inheritance); - checkYl(record, filteredFamily, inheritance); - inheritance.setDenovo(deNovoChecker.checkDeNovo(record, sample)); - return inheritance; - } - - private void checkMt(VcfRecord vcfRecord, Pedigree family, - Inheritance inheritance) { - MatchEnum isMt = mtChecker.check(vcfRecord, family); - if (isMt != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.MT, isMt == POTENTIAL)); - } - } - - private void checkYl(VcfRecord vcfRecord, Pedigree family, - Inheritance inheritance) { - MatchEnum isYl = ylChecker.check(vcfRecord, family); - if (isYl != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.YL, isYl == POTENTIAL)); - } } - private void checkXl(VcfRecord vcfRecord, Pedigree family, - Inheritance inheritance) { - MatchEnum isXld = xldChecker.check(vcfRecord, family); - if (isXld != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.XLD, isXld == POTENTIAL)); + MatchEnum check(VariantGeneRecord record, Pedigree pedigree, InheritanceMode mode) { + MatchEnum result; + switch(mode){ + case AD -> result = adChecker.check(record, pedigree); + case AD_IP -> result = adNonPenetranceChecker.check(record, pedigree); + case AR -> result = arChecker.check(record, pedigree); + case XLR -> result = xlrChecker.check(record, pedigree); + case XLD -> result = xldChecker.check(record, pedigree); + case MT -> result = mtChecker.check(record, pedigree); + case YL -> result = ylChecker.check(record, pedigree); + default -> throw new UnexpectedEnumException(mode); } - MatchEnum isXlr = xlrChecker.check(vcfRecord, family); - if (isXlr != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.XLR, isXlr == POTENTIAL)); - } - } - - private void checkAd(VcfRecord vcfRecord, Pedigree family, - Inheritance inheritance) { - MatchEnum isAd = adChecker.check(vcfRecord, family); - if (isAd != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AD, isAd == POTENTIAL)); - } else { - MatchEnum isAdNonPenetrance = adNonPenetranceChecker.check(vcfRecord, family, isAd); - if (isAdNonPenetrance != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AD_IP, isAdNonPenetrance == POTENTIAL)); - } - } - } - - private void checkAr(Map> geneVariantMap, - VcfRecord vcfRecord, Pedigree family, - Inheritance inheritance, ArCompoundChecker arCompoundChecker) { - MatchEnum isAr = arChecker.check(vcfRecord, family); - if (isAr != FALSE) { - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AR, isAr == POTENTIAL)); - } - List compounds = arCompoundChecker - .check(geneVariantMap, vcfRecord, family, isAr); - if (!compounds.isEmpty()) { - boolean isCertain = compounds.stream().anyMatch(CompoundCheckResult::isCertain); - inheritance.addInheritanceMode(new PedigreeInheritanceMatch(InheritanceMode.AR_C, !isCertain)); - inheritance.setCompounds(compounds.stream().map(compoundCheckResult -> createKey(compoundCheckResult.getPossibleCompound())).collect( - Collectors.toSet())); - } - } - - private String createKey(VcfRecord vcfRecord) { - return String.format("%s_%s_%s_%s", vcfRecord.getContig(), vcfRecord.getStart(), - vcfRecord.getReference().getBaseString(), - vcfRecord.getAlternateAlleles().stream().map(Allele::getBaseString) - .collect(Collectors.joining("/"))); + return result; } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java index b662afc..f1db54f 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java @@ -1,11 +1,10 @@ package org.molgenis.vcf.inheritance.matcher; +import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFHeader; -import java.io.Closeable; - public interface RecordWriter { - void add(VcfRecord vcfRecord); + void add(VariantContext variantContext); void writeHeader(VCFHeader vcfHeader); void close(); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java index 165753e..34c8f76 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java @@ -1,6 +1,8 @@ package org.molgenis.vcf.inheritance.matcher; import static java.util.Objects.requireNonNull; + +import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.variantcontext.writer.VariantContextWriter; import htsjdk.variant.vcf.VCFHeader; @@ -20,8 +22,8 @@ public void writeHeader(VCFHeader vcfHeader) { } @Override - public void add(VcfRecord vcfRecord) { - this.vcfWriter.add(vcfRecord.unwrap()); + public void add(VariantContext vc) { + this.vcfWriter.add(vc); } @Override diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java index 4421c89..1b4a5ed 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java @@ -1,29 +1,45 @@ package org.molgenis.vcf.inheritance.matcher; -import htsjdk.variant.variantcontext.VariantContext; +import htsjdk.variant.variantcontext.Allele; +import org.molgenis.vcf.utils.sample.model.Pedigree; + +import java.util.HashSet; +import java.util.Set; public class VariantContextUtils { private VariantContextUtils() { } - public static boolean onAutosome(VcfRecord vcfRecord) { - String contigId = vcfRecord.getContig(); + public static boolean onAutosome(VariantGeneRecord variantGeneRecord) { + String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isAutosome(contigId); } - public static boolean onChromosomeX(VcfRecord vcfRecord) { - String contigId = vcfRecord.getContig(); + public static boolean onChromosomeX(VariantGeneRecord variantGeneRecord) { + String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeX(contigId); } - public static boolean onChromosomeY(VcfRecord vcfRecord) { - String contigId = vcfRecord.getContig(); + public static boolean onChromosomeMt(VariantGeneRecord variantGeneRecord) { + String contigId = variantGeneRecord.getContig(); + return contigId != null && ContigUtils.isChromosomeMt(contigId); + } + + public static boolean onChromosomeY(VariantGeneRecord variantGeneRecord) { + String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeY(contigId); } - public static boolean onChromosomeMt(VcfRecord vcfRecord) { - String contigId = vcfRecord.getContig(); - return contigId != null && ContigUtils.isChromosomeMt(contigId); + public static Set getAltAlleles(VariantGeneRecord variantGeneRecord, Pedigree pedigree){ + Set altAlleles = new HashSet<>(); + for(String sample : pedigree.getMembers().keySet()){ + EffectiveGenotype effectiveGenotype = variantGeneRecord.getGenotype(sample); + if(effectiveGenotype != null) { + effectiveGenotype.unwrap().getAlleles().stream().filter(Allele::isNonReference).forEach(altAlleles::add); + } + } + return altAlleles; } + } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java new file mode 100644 index 0000000..65019cf --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java @@ -0,0 +1,56 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.VariantContext; +import lombok.Getter; +import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; + +import java.util.*; + +import static java.util.Objects.requireNonNull; + +public class VariantGeneRecord { + + private final VariantContext variantContext; + @Getter + private final Set pathogenicAlleles; + @Getter + private final GeneInfo geneInfo; + + public VariantGeneRecord(VariantContext variantContext, Set pathogenicAlleles, GeneInfo geneInfo) { + this.variantContext = requireNonNull(variantContext); + this.pathogenicAlleles = requireNonNull(pathogenicAlleles); + this.geneInfo = requireNonNull(geneInfo); + } + + public EffectiveGenotype getGenotype(String sampleId) { + htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); + if (gt == null) { + return null; + } + if(pathogenicAlleles.isEmpty()){ + pathogenicAlleles.addAll(variantContext.getAlternateAlleles()); + } + return new EffectiveGenotype(gt); + } + + public List getAlternateAlleles() { + return variantContext.getAlternateAlleles(); + } + + public VariantContext unwrap() { + return variantContext; + } + + public String getContig() { + return variantContext.getContig(); + } + + public int getStart() { + return variantContext.getStart(); + } + + public Allele getReference() { + return variantContext.getReference(); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java new file mode 100644 index 0000000..1386d84 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java @@ -0,0 +1,20 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.Genotype; +import htsjdk.variant.variantcontext.VariantContext; +import lombok.NonNull; +import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; +import org.molgenis.vcf.inheritance.matcher.model.InheritanceResult; + +import java.util.Map; + +public record VariantRecord(Map variantGeneRecords, VariantContext variantContext, + InheritanceResult inheritanceResult) { + public Genotype getGenotype(@NonNull String individualId) { + return variantContext.getGenotype(individualId); + } + + public String getContig() { + return variantContext.getContig(); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java index 22e904f..b530e0a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java @@ -4,6 +4,7 @@ import htsjdk.variant.vcf.VCFFileReader; import htsjdk.variant.vcf.VCFHeader; +import lombok.Getter; import java.util.Set; import java.util.stream.Stream; @@ -15,28 +16,18 @@ public class VcfReader implements AutoCloseable { private final VCFFileReader vcfFileReader; - private final VepMetadata vepMetadata; + @Getter + private final VcfRecordFactory vcfRecordFactory; private final Set pathogenicClasses; - public VcfReader(VCFFileReader vcfFileReader, VepMetadata vepMetadata, Set pathogenicClasses) { + public VcfReader(VCFFileReader vcfFileReader, VcfRecordFactory vcfRecordFactory, Set pathogenicClasses) { this.vcfFileReader = requireNonNull(vcfFileReader); - this.vepMetadata = vepMetadata; + this.vcfRecordFactory = vcfRecordFactory; this.pathogenicClasses = pathogenicClasses; } - public Stream stream() { - //FIXME - return StreamSupport.stream(vcfFileReader.spliterator(), false).map(vc -> new VcfRecord(vc, vepMetadata, pathogenicClasses)); - } - - public Stream filteredStream(Set classes) { - //FIXME: filter on classes - return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, vepMetadata, pathogenicClasses)); - } - - public Stream filteredStream(Set classes, String geneId) { - //FIXME: filter on classes and geneId - return StreamSupport.stream(vcfFileReader.spliterator(), false).filter(variantContext->{return variantContext != null;}).map(vc -> new VcfRecord(vc, vepMetadata, pathogenicClasses)); + public Stream stream() { + return StreamSupport.stream(vcfFileReader.spliterator(), false).map(vc -> vcfRecordFactory.create(vc, pathogenicClasses)); } @Override diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java index a5fd711..51ef3fc 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java @@ -19,6 +19,7 @@ public VcfReaderFactoryImpl(VepMetadataServiceFactoryImpl vepMetadataServiceFact public VcfReader create(Settings settings) { Path inputVcfPath = settings.getInputVcfPath(); VCFFileReader vcfFileReader = new VCFFileReader(inputVcfPath.toFile(), false); - return new VcfReader(vcfFileReader, new VepMetadata(vcfFileReader.getFileHeader(), vepMetadataServiceFactoryImpl.create()), settings.getPathogenicClasses()); + VepMetadata vepMetadata = new VepMetadata(vcfFileReader.getFileHeader(), vepMetadataServiceFactoryImpl.create()); + return new VcfReader(vcfFileReader, new VcfRecordFactoryImpl(vepMetadata), settings.getPathogenicClasses()); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java deleted file mode 100644 index 0eafdaf..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecord.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.VariantContext; -import lombok.Getter; -import org.molgenis.vcf.inheritance.matcher.model.Gene; -import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; -import org.molgenis.vcf.inheritance.matcher.model.VcfRecordGenes; - -import java.util.*; - -import static java.util.Collections.emptyMap; -import static java.util.Objects.requireNonNull; - -public class VcfRecord { - private final VariantContext variantContext; - @Getter - private final VepMetadata vepMetadata; - @Getter - private final Set pathogenicClasses; - - public VcfRecord(VariantContext variantContext, VepMetadata vepMetadata, Set pathogenicClasses) { - this.variantContext = requireNonNull(variantContext); - this.vepMetadata = requireNonNull(vepMetadata); - this.pathogenicClasses = requireNonNull(pathogenicClasses); - } - - public EffectiveGenotype getGenotype(String sampleId){ - htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); - if(gt == null){ - return null; - } - return new EffectiveGenotype(gt, variantContext, getPathogenicAlleles()); - } - - private List getPathogenicAlleles() { - List pathogenicAlleles = new ArrayList(); - if(pathogenicClasses.isEmpty()){ - pathogenicAlleles = variantContext.getAlternateAlleles(); - }else { - for (int i = 1; i <= variantContext.getAlternateAlleles().size(); i++) { - Allele allele = variantContext.getAlleles().get(i); - if(getClassesForAllele(i).stream().anyMatch(pathogenicClasses::contains)) { - pathogenicAlleles.add(allele); - } - } - } - return pathogenicAlleles; - } - - public List getAttributeAsStringList(String vepFieldId) { - return variantContext.getAttributeAsStringList(vepFieldId, ""); - } - - public List getAlternateAlleles() { - return variantContext.getAlternateAlleles(); - } - - public VariantContext unwrap() { - return variantContext; - } - - public String getContig() { - return variantContext.getContig(); - } - - public int getStart() { - return variantContext.getStart(); - } - - public Allele getReference() { - return variantContext.getReference(); - } - - - public VcfRecordGenes getVcfRecordGenes() { - return getVcfRecordGenes(emptyMap()); - } - - public VcfRecordGenes getVcfRecordGenes(Map knownGenes) { - VcfRecordGenes.VcfRecordGenesBuilder genesBuilder = VcfRecordGenes.builder(); - Map genes = new HashMap<>(); - List vepValues = getAttributeAsStringList(vepMetadata.getVepFieldId()); - for (String vepValue : vepValues) { - String[] vepSplit = vepValue.split("\\|", -1); - String gene = vepSplit[vepMetadata.getGeneIndex()]; - String source = vepSplit[vepMetadata.getGeneSourceIndex()]; - if (gene.isEmpty() || source.isEmpty()) { - genesBuilder.containsVcWithoutGene(true); - continue; - } - - if (!knownGenes.containsKey(gene)) { - Set modes = new HashSet<>(); - if (vepMetadata.getInheritanceIndex() != -1) { - String[] inheritanceModes - = vepSplit[vepMetadata.getInheritanceIndex()].split("&"); - mapGeneInheritance(modes, inheritanceModes); - } - genes.put(gene, new Gene(gene, source, modes)); - } else { - genes.put(gene, knownGenes.get(gene)); - } - } - genesBuilder.genes(genes); - return genesBuilder.build(); - } - - public Set getClassesForAllele(int alleleIndex){ - List vepValues = getAttributeAsStringList(vepMetadata.getVepFieldId()); - Set classes = new HashSet<>(); - for (String vepValue : vepValues) { - String[] vepSplit = vepValue.split("\\|", -1); - int csqAlleleIndex = Integer.parseInt(vepSplit[vepMetadata.getAlleleNumIndex()]); - if(csqAlleleIndex == alleleIndex){ - classes.add(vepSplit[vepMetadata.getClassIndex()]); - } - } - return classes; - } - - private void mapGeneInheritance(Set modes, String[] inheritanceModes) { - for (String mode : inheritanceModes) { - switch (mode) { - case "AR" -> modes.add(InheritanceMode.AR); - case "AD" -> modes.add(InheritanceMode.AD); - case "XLR" -> modes.add(InheritanceMode.XLR); - case "XLD" -> modes.add(InheritanceMode.XLD); - case "XL" -> { - modes.add(InheritanceMode.XLR); - modes.add(InheritanceMode.XLD); - } - default -> { - //We ignore all the modes that are not used for matching. - } - } - } - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java new file mode 100644 index 0000000..2bbc9ad --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java @@ -0,0 +1,9 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.VariantContext; + +import java.util.Set; + +public interface VcfRecordFactory { + VariantRecord create(VariantContext variantContext, Set pathogenicClasses); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java new file mode 100644 index 0000000..56a5dde --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java @@ -0,0 +1,101 @@ +package org.molgenis.vcf.inheritance.matcher; + +import htsjdk.variant.variantcontext.Allele; +import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.model.InheritanceResult; +import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; +import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; + +import java.util.*; + +import static java.util.Collections.emptySet; +import static java.util.Objects.requireNonNull; + +public class VcfRecordFactoryImpl implements VcfRecordFactory { + private final VepMetadata vepMetadata; + + public VcfRecordFactoryImpl(VepMetadata vepMetadata) { + this.vepMetadata = requireNonNull(vepMetadata); + } + + @Override + public VariantRecord create(VariantContext variantContext, Set pathogenicClasses) { + Map result = new HashMap<>(); + for (GeneInfo geneInfo : getVcfGeneInfos(variantContext)) { + Set pathogenicAlleles = getPathogenicAlleles(variantContext, vepMetadata, pathogenicClasses, geneInfo); + result.put(geneInfo, new VariantGeneRecord(variantContext, pathogenicAlleles, geneInfo)); + } + return new VariantRecord(result, variantContext, InheritanceResult.builder().build()); + } + + private Set getVcfGeneInfos(VariantContext variantContext) { + List vepValues = getAttributeAsStringList(variantContext, vepMetadata.getVepFieldId()); + Set result = new HashSet<>(); + for (String vepValue : vepValues) { + String[] vepSplit = vepValue.split("\\|", -1); + String geneId = vepSplit[vepMetadata.getGeneIndex()]; + String symbolSource = vepSplit[vepMetadata.getGeneSourceIndex()]; + Set inheritanceModes = vepMetadata.getInheritanceIndex() != -1 ? mapGeneInheritance(vepSplit[vepMetadata.getInheritanceIndex()]): emptySet(); + result.add(new GeneInfo(geneId, symbolSource, inheritanceModes)); + } + return result; + } + + private Set getPathogenicAlleles(VariantContext variantContext, VepMetadata vepMetadata, Set pathogenicClasses, GeneInfo geneInfo) { + Set pathogenicAlleles = new HashSet<>(); + + for (int i = 1; i <= variantContext.getAlternateAlleles().size(); i++) { + Allele allele = variantContext.getAlleles().get(i); + if(isAllelePathogenic(variantContext, vepMetadata, i, geneInfo, pathogenicClasses)) { + pathogenicAlleles.add(allele); + } + } + return pathogenicAlleles; + } + + public boolean isAllelePathogenic(VariantContext variantContext, VepMetadata vepMetadata, int alleleIndex, GeneInfo geneInfo, Set pathogenicClasses) { + if(pathogenicClasses.isEmpty()){ + return true; + } + if ((vepMetadata.getAlleleNumIndex() == -1 || vepMetadata.getClassIndex() == -1)) { + throw new UnsupportedOperationException("Classes mapping provided, but input VCF is missing ALLELE_NUM or VIPC VEP annotations"); + } + List vepValues = getAttributeAsStringList(variantContext, vepMetadata.getVepFieldId()); + boolean result = false; + for (String vepValue : vepValues) { + String[] vepSplit = vepValue.split("\\|", -1); + int csqAlleleIndex = Integer.parseInt(vepSplit[vepMetadata.getAlleleNumIndex()]); + if (csqAlleleIndex == alleleIndex) { + if (geneInfo.geneId().equals(vepSplit[vepMetadata.getGeneIndex()])) { + result = pathogenicClasses.contains(vepSplit[vepMetadata.getClassIndex()]); + } + } + } + return result; + } + + public List getAttributeAsStringList(VariantContext variantContext, String vepFieldId) { + return variantContext.getAttributeAsStringList(vepFieldId, ""); + } + + private Set mapGeneInheritance(String inheritanceString) { + Set modes = new HashSet<>(); + String[] inheritanceModes = inheritanceString.split(","); + for (String mode : inheritanceModes) { + switch (mode) { + case "AR" -> modes.add(InheritanceMode.AR); + case "AD" -> modes.add(InheritanceMode.AD); + case "XLR" -> modes.add(InheritanceMode.XLR); + case "XLD" -> modes.add(InheritanceMode.XLD); + case "XL" -> { + modes.add(InheritanceMode.XLR); + modes.add(InheritanceMode.XLD); + } + default -> { + //We ignore all the modes that are not used for matching. + } + } + } + return modes; + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java index baf049b..02b20c6 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java @@ -18,8 +18,8 @@ public class VepMetadata { private static final String INFO_DESCRIPTION_PREFIX = "Consequence annotations from Ensembl VEP. Format: "; private static final String INHERITANCE = "InheritanceModesGene"; - private VCFHeader vcfHeader = null; - private FieldMetadataService fieldMetadataService = null; + private final VCFHeader vcfHeader; + private final FieldMetadataService fieldMetadataService; @Getter private String vepFieldId = null; @Getter @@ -63,14 +63,4 @@ private void init() { } throw new MissingInfoException("VEP"); } - - //For testing purposes - public VepMetadata(String vepFieldId, int geneIndex, int geneSourceIndex, int inheritanceIndex, int alleleNumIndex, int classIndex) { - this.vepFieldId = vepFieldId; - this.geneIndex = geneIndex; - this.geneSourceIndex = geneSourceIndex; - this.inheritanceIndex = inheritanceIndex; - this.alleleNumIndex = alleleNumIndex; - this.classIndex = classIndex; - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index b9482c9..b8b855e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -2,83 +2,112 @@ import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; +import java.util.*; + import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; /** * Autosomal dominant (AD) inheritance pattern matcher */ @Component -public class AdChecker extends InheritanceChecker{ +public class AdChecker { /** * Check whether the AD inheritance pattern could match for a variant in a pedigree */ public MatchEnum check( - VcfRecord vcfRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(vcfRecord)) { + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantGeneRecord)) { return FALSE; } - return checkFamily(vcfRecord, family); + return checkFamily(variantGeneRecord, family); } - MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - if (sampleGt == null || sampleGt.isNoCall()) { - return POTENTIAL; - } else { - if (sampleGt.isMixed()) { - return checkMixed(sample, sampleGt); - } else { - if (sampleGt.hasAltAllele()) { - return checkSampleWithVariant(sample); - } else { - return checkSampleWithoutVariant(sample); + private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ + matches.add(POTENTIAL); + } + return merge(matches); + } + + private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if(genotype == null){ + matches.add(POTENTIAL); + } + else if(genotype.isHomRef()){ + matches.add(TRUE); + } + else { + for (EffectiveGenotype affectedGenotype : affectedGenotypes) { + if (affectedGenotype.hasAlt() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( + allele -> genotype.getAlleles().contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); + } } } } + return merge(matches); } - private static MatchEnum checkSampleWithoutVariant(Sample sample) { - return switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> FALSE; - case UNAFFECTED -> TRUE; - case MISSING -> POTENTIAL; - }; + private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + affectedGenotypes.add(genotype); + if (genotype.isHomRef()) { + return FALSE; + } else if ((genotype.hasMissingAllele() && genotype.hasReference()) || genotype.isNoCall()) { + matches.add(POTENTIAL); + } else { + matches.add(TRUE); + } + } + return merge(matches); } - private static MatchEnum checkSampleWithVariant(Sample sample) { - return switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> TRUE; - case UNAFFECTED -> FALSE; - case MISSING -> POTENTIAL; - }; + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { + return FALSE; + } else if (matches.contains(POTENTIAL)) { + return POTENTIAL; + } + return TRUE; } - private static MatchEnum checkMixed(Sample sample, EffectiveGenotype sampleGt) { - switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> { - if (!sampleGt.hasAltAllele()) { - return POTENTIAL; - } - } - case UNAFFECTED -> { - if (sampleGt.hasAltAllele()) { - return FALSE; - } else { - return POTENTIAL; - } - } - case MISSING -> { - return POTENTIAL; + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); } - default -> throw new IllegalArgumentException(); } - return TRUE; + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java index 0fb3314..b96492e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java @@ -4,7 +4,7 @@ import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -14,25 +14,25 @@ public class AdNonPenetranceChecker extends InheritanceChecker{ public MatchEnum check( - VcfRecord vcfRecord, Pedigree family, MatchEnum isAd) { - if (!VariantContextUtils.onAutosome(vcfRecord) || isAd == TRUE) { + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantGeneRecord)) { return FALSE; } - return checkFamily(vcfRecord, family); + return checkFamily(variantGeneRecord, family); } - MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + MatchEnum checkSample(Sample sample, VariantGeneRecord variantGeneRecord) { + EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - if (sampleGt.isMixed()) { - return sampleGt.hasAltAllele() ? TRUE : POTENTIAL; + if(sampleGt.isHomRef()){ + return FALSE; } - if(sampleGt.isNoCall()){ - return POTENTIAL; - }else{ - return sampleGt.isHomRef() ? FALSE : TRUE; + else if (sampleGt.isMixed()) { + return sampleGt.hasAlt() ? TRUE : POTENTIAL; + } else{ + return TRUE; } } case UNAFFECTED -> { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java index bd99c61..44ff1d2 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java @@ -1,74 +1,105 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; +import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; +import java.util.*; + @Component -public class ArChecker extends InheritanceChecker{ +public class ArChecker { + + public MatchEnum check( + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantGeneRecord)) { + return FALSE; + } - public MatchEnum check( - VcfRecord vcfRecord, Pedigree family) { - if (!onAutosome(vcfRecord)) { - return FALSE; + return checkFamily(variantGeneRecord, family); } - return checkFamily(vcfRecord, family); - } + private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set> affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + Set affectedAltAlleles = new HashSet<>(); + affectedGenotypes.forEach(alleles -> alleles.stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); + if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { + matches.add(POTENTIAL); + } + return merge(matches); + } - @Override - MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - if (sampleGt == null || sampleGt.isNoCall()) { - return POTENTIAL; - } else { - if (sampleGt.isMixed()) { - return checkMixed(sample, sampleGt); - } else { - if (sampleGt.hasAltAllele()) { - return checkSampleWithVariant(sample, sampleGt); - } else { - return checkSampleWithoutVariant(sample); + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { + return FALSE; + } else if (matches.contains(POTENTIAL)) { + return POTENTIAL; } - } + return TRUE; } - } - private static MatchEnum checkSampleWithoutVariant(Sample sample) { - return switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> FALSE; - case UNAFFECTED -> TRUE; - case MISSING -> POTENTIAL; - }; - } + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); + } + } + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; + } - private static MatchEnum checkSampleWithVariant(Sample sample, EffectiveGenotype sampleGt) { - return switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> sampleGt.isHom() ? TRUE : FALSE; - case UNAFFECTED -> sampleGt.isHet() ? TRUE : FALSE; - case MISSING -> POTENTIAL; - }; - } + private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if(genotype == null){ + matches.add(POTENTIAL); + } else if (genotype.hasReference()) { + matches.add(TRUE); + } else if (genotype.getAlleles().stream().allMatch( + allele -> allele.isCalled() && affectedAlleles.contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); + } + } + return merge(matches); + } - private static MatchEnum checkMixed(Sample sample, EffectiveGenotype sampleGt) { - switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> { - if (!sampleGt.hasAltAllele()) { - return FALSE; - } else { - return POTENTIAL; + private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set> affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + affectedGenotypes.add(genotype.getAlleles()); + if (genotype.hasReference()) { + return FALSE; + } else if ((genotype.isMixed()) || genotype.isNoCall()) { + matches.add(POTENTIAL); + } else { + matches.add(TRUE); + } } - } - case UNAFFECTED, MISSING -> { - return POTENTIAL; - } - default -> throw new IllegalArgumentException(); + return merge(matches); } - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index ee28361..94ca44a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -2,52 +2,40 @@ import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.isAlt; import htsjdk.variant.variantcontext.Allele; import java.util.*; -import htsjdk.variant.variantcontext.GenotypeBuilder; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; -import org.molgenis.vcf.inheritance.matcher.model.Gene; +import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; public class ArCompoundChecker { - private final VepMetadata vepMetadata; - - public ArCompoundChecker(VepMetadata vepMetadata) { - this.vepMetadata = vepMetadata; - } - - public List check( - Map> geneVariantMap, - VcfRecord vcfRecord, Pedigree family, MatchEnum isAr) { - if (onAutosome(vcfRecord) && isAr != TRUE) { - List compounds = new ArrayList<>(); - Map genes = vcfRecord.getVcfRecordGenes().getGenes(); - for (Gene gene : genes.values()) { - checkForGene(geneVariantMap, vcfRecord, family, compounds, gene); - } + public Set check( + Map> geneVariantMap, + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (onAutosome(variantGeneRecord)) { + Set compounds = new HashSet<>(); + checkForGene(geneVariantMap, variantGeneRecord, family, compounds); return compounds; } - return Collections.emptyList(); + return Collections.emptySet(); } - private void checkForGene(Map> geneVariantMap, - VcfRecord vcfRecord, Pedigree family, List compounds, - Gene gene) { - List variantContexts = geneVariantMap.get(gene.getId()); - if (variantContexts != null) { - for (VcfRecord otherRecord : variantContexts) { - if (!otherRecord.equals(vcfRecord)) { - MatchEnum isPossibleCompound = checkFamily(family, vcfRecord, otherRecord); + private void checkForGene(Map> geneVariantMap, + VariantGeneRecord variantGeneRecord, Pedigree family, Set compounds) { + Collection variantGeneRecords = geneVariantMap.get(variantGeneRecord.getGeneInfo()); + if (variantGeneRecords != null) { + for (VariantGeneRecord otherRecord : variantGeneRecords) { + if (!otherRecord.equals(variantGeneRecord)) { + MatchEnum isPossibleCompound = checkFamily(family, variantGeneRecord, otherRecord); if (isPossibleCompound != FALSE) { CompoundCheckResult result = CompoundCheckResult.builder().possibleCompound(otherRecord).isCertain(isPossibleCompound != POTENTIAL).build(); compounds.add(result); @@ -57,99 +45,118 @@ private void checkForGene(Map> geneVariantMap, } } - private MatchEnum checkFamily(Pedigree family, VcfRecord vcfRecord, - VcfRecord otherVcfRecord) { - Set results = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, vcfRecord, otherVcfRecord)); + private MatchEnum checkFamily(Pedigree family, VariantGeneRecord variantGeneRecord, + VariantGeneRecord otherVariantGeneRecord) { + Map> membersByStatus = getMembersByStatus(family); + Set> affectedGenotypes = new HashSet<>(); + Set> otherAffectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); + matches.add(checkUnaffected(variantGeneRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); + if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ + matches.add(POTENTIAL); } - if (results.contains(FALSE)) { - return FALSE; - } else if (results.contains(POTENTIAL)) { - return POTENTIAL; + return merge(matches); + } + + private MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, VariantGeneRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + matches.add(checkUnaffectedSample(variantGeneRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, unAffectedSample)); } - return TRUE; + return merge(matches); } - private MatchEnum checkSample(Sample sample, VcfRecord vcfRecord, VcfRecord otherVcfRecord) { - //Affected individuals have to be het. for both variants - //Healthy individuals can be het. for one of the variants but cannot have both variants + private static MatchEnum checkUnaffectedSample(VariantGeneRecord variantGeneRecord, VariantGeneRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample unAffectedSample) { + Set matches = new HashSet<>(); + matches.add(checkSingleUnaffectedSampleVariant(variantGeneRecord, affectedGenotypes, unAffectedSample)); + matches.add(checkSingleUnaffectedSampleVariant(otherVariantGeneRecord, otherAffectedGenotypes, unAffectedSample)); + if(matches.contains(TRUE)){ + return TRUE; + } else if (matches.contains(POTENTIAL)) { + return POTENTIAL; + } - EffectiveGenotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - EffectiveGenotype sampleOtherGt = otherVcfRecord.getGenotype(sample.getPerson().getIndividualId()); - sampleGt = sampleGt != null ? sampleGt : new EffectiveGenotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), vcfRecord.unwrap(), Collections.emptyList()); - sampleOtherGt = sampleOtherGt != null ? sampleOtherGt : new EffectiveGenotype(GenotypeBuilder.createMissing(sample.getPerson().getIndividualId(), 2), otherVcfRecord.unwrap(), Collections.emptyList()); - return switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> checkAffectedSample(sampleGt, sampleOtherGt); - case UNAFFECTED -> checkUnaffectedSample(sampleGt, sampleOtherGt); - case MISSING -> POTENTIAL; - }; + EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if(sampleGt.isPhased() && sampleOtherGt.isPhased() && + (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || + (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference())){ + return TRUE; + } + return FALSE; } - private MatchEnum checkAffectedSample(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { - if (sampleGt.isHomRef() || sampleOtherGt.isHomRef()) { - return FALSE; - } else if (sampleGt.isHomAlt() - || sampleOtherGt.isHomAlt()) { - return FALSE; - } else if (sampleGt.isPhased() && sampleOtherGt.isPhased()) { - return checkSamplePhased(sampleGt, sampleOtherGt, true); + private static MatchEnum checkSingleUnaffectedSampleVariant(VariantGeneRecord variantGeneRecord, Set> affectedGenotypes, Sample unAffectedSample) { + Set matches = new HashSet<>(); + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + for (List affectedGenotype : affectedGenotypes) { + if(genotype != null && genotype.isHomRef()){ + matches.add(TRUE); + } + else if (affectedGenotype.stream().filter(Allele::isNonReference).allMatch( + allele -> allele.isCalled() && genotype!= null && genotype.getAlleles().contains(allele))) { + matches.add(FALSE); + } else{ + matches.add(POTENTIAL); + } } - return checkAffectedSampleUnphased(sampleGt, sampleOtherGt); + return merge(matches); } - private MatchEnum checkUnaffectedSample(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { - if ((sampleGt.isNoCall() && (sampleOtherGt.hasAltAllele() || sampleOtherGt.isNoCall())) - || sampleOtherGt.isNoCall() && (sampleGt.hasAltAllele())) { - return POTENTIAL; - } else if (sampleGt.isHomAlt() || sampleOtherGt.isHomAlt()) { - return FALSE; - } else if (sampleGt.isPhased() && sampleOtherGt.isPhased()) { - return checkSamplePhased(sampleGt, sampleOtherGt, false); + private MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, VariantGeneRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + if(sampleGt != null) { + affectedGenotypes.add(sampleGt.getAlleles()); + } + if(sampleOtherGt != null) { + otherAffectedGenotypes.add(sampleOtherGt.getAlleles()); + } + if((sampleGt != null && sampleGt.isHom()) || (sampleOtherGt != null && sampleOtherGt.isHom())){ + return FALSE; + } else if ((sampleGt == null || !sampleGt.hasReference()) || (sampleOtherGt == null || !sampleOtherGt.hasReference())) { + matches.add(POTENTIAL); + } else{ + if(sampleGt.isPhased() && sampleOtherGt.isPhased() && + (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || + (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference())){ + return FALSE; + } + matches.add(TRUE); + } } - return checkUnaffectedSampleUnphased(sampleGt, sampleOtherGt); + return merge(matches); } - private MatchEnum checkUnaffectedSampleUnphased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { - boolean sampleContainsAlt = sampleGt.hasAltAllele(); - boolean sampleOtherGtContainsAlt = sampleOtherGt.hasAltAllele(); - if (sampleContainsAlt && sampleOtherGtContainsAlt) { + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { return FALSE; - } else if ((sampleContainsAlt || sampleGt.isMixed() || sampleGt.isNoCall()) && - (sampleOtherGtContainsAlt || sampleOtherGt.isMixed() || sampleOtherGt.isNoCall())) { + } else if (matches.contains(POTENTIAL)) { return POTENTIAL; } return TRUE; } - private MatchEnum checkSamplePhased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt, boolean isAffected) { - Allele allele1 = sampleGt.getAllele(0); - Allele allele2 = sampleGt.getAllele(1); - Allele otherAllele1 = sampleOtherGt.getAllele(0); - Allele otherAllele2 = sampleOtherGt.getAllele(1); - //For phased data both variants can be present in an unaffected individual if both are on the same allele - if ((isAlt(allele1) && isAlt(otherAllele2)) || isAlt(allele2) && isAlt(otherAllele1)) { - return isAffected ? TRUE : FALSE; - } - if ((allele1.isReference() && otherAllele1.isReference()) || (allele2.isReference() && otherAllele2.isReference())) { - return isAffected? FALSE : TRUE; - } - return POTENTIAL; - } - - private MatchEnum checkAffectedSampleUnphased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { - if (sampleGt.hasAltAllele() && !sampleGt.isHom() && sampleOtherGt.hasAltAllele() && !sampleOtherGt.isHom()) { - return TRUE; - } - boolean gtMissingOrMixed = sampleGt.isNoCall() || sampleGt.isMixed(); - boolean otherGtMissingOrMixed = sampleOtherGt.isNoCall() || sampleOtherGt.isMixed(); - boolean hasVariantAndOtherGtMissing = sampleGt.hasAltAllele() && !sampleGt.isHom() && otherGtMissingOrMixed; - boolean hasOtherVariantAndGtMissing = gtMissingOrMixed && sampleOtherGt.hasAltAllele() && !sampleOtherGt.isHom(); - if (hasVariantAndOtherGtMissing - || hasOtherVariantAndGtMissing - || (gtMissingOrMixed && otherGtMissingOrMixed)) { - return POTENTIAL; + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); + } } - return FALSE; + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java index 710e2b4..e759780 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java @@ -1,11 +1,11 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.*; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.*; import htsjdk.variant.variantcontext.Genotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.ContigUtils; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; import org.molgenis.vcf.utils.sample.model.Sex; @@ -15,15 +15,17 @@ public class DeNovoChecker { //use original GT instead of inheritance matcher specific one since we are looking for "new alleles" not specifically pathogenic ones - public MatchEnum checkDeNovo(VcfRecord vcfRecord, Sample proband) { - Genotype probandGt = vcfRecord.getGenotype(proband.getPerson().getIndividualId()) != null ? vcfRecord.getGenotype(proband.getPerson().getIndividualId()).unwrap() : null; - Genotype fatherGt = vcfRecord.getGenotype(proband.getPerson().getPaternalId()) != null ? vcfRecord.getGenotype(proband.getPerson().getPaternalId()).unwrap() : null; - Genotype motherGt = vcfRecord.getGenotype(proband.getPerson().getMaternalId()) != null ? vcfRecord.getGenotype(proband.getPerson().getMaternalId()).unwrap() : null; + public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { + Genotype probandGt = variantRecord.getGenotype(proband.getPerson().getIndividualId()); + Genotype fatherGt = variantRecord.getGenotype(proband.getPerson().getPaternalId()); + Genotype motherGt = variantRecord.getGenotype(proband.getPerson().getMaternalId()); if (!hasParents(proband)) { return POTENTIAL; } - if (onChromosomeX(vcfRecord) && proband.getPerson().getSex() == Sex.MALE) { + + String contigId = variantRecord.getContig(); + if ((contigId != null && ContigUtils.isChromosomeX(contigId)) && proband.getPerson().getSex() == Sex.MALE) { if (probandGt.hasAltAllele()) { if (motherGt.hasAltAllele()) { return FALSE; @@ -34,9 +36,9 @@ public MatchEnum checkDeNovo(VcfRecord vcfRecord, Sample proband) { } } return probandGt.isNoCall() ? POTENTIAL : FALSE; - } else if (onChromosomeY(vcfRecord)) { + } else if ((contigId != null && ContigUtils.isChromosomeY(contigId))) { return checkYLinkedVariant(proband, probandGt, fatherGt); - } else if (onChromosomeMt(vcfRecord)) { + } else if ((contigId != null && ContigUtils.isChromosomeMt(contigId))) { return checkMtVariant(probandGt, motherGt); } else { return checkRegular(probandGt, fatherGt, motherGt); @@ -44,14 +46,11 @@ public MatchEnum checkDeNovo(VcfRecord vcfRecord, Sample proband) { } private static MatchEnum checkYLinkedVariant(Sample proband, Genotype probandGt, Genotype fatherGt) { - switch (proband.getPerson().getSex()) { - case MALE: - return checkYLinkedVariantMale(probandGt, fatherGt); - case FEMALE: - return FALSE; - default: - return (fatherGt.hasAltAllele() || !probandGt.hasAltAllele()) ? FALSE : POTENTIAL; - } + return switch (proband.getPerson().getSex()) { + case MALE -> checkYLinkedVariantMale(probandGt, fatherGt); + case FEMALE -> FALSE; + default -> (fatherGt.hasAltAllele() || !probandGt.hasAltAllele()) ? FALSE : POTENTIAL; + }; } private static MatchEnum checkYLinkedVariantMale(Genotype probandGt, Genotype fatherGt) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java deleted file mode 100644 index 696827c..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/HaploidChecker.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher.checker; - -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; -import org.molgenis.vcf.utils.sample.model.Sample; - -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; - -public abstract class HaploidChecker extends InheritanceChecker{ - protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - EffectiveGenotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> { - return checkAffected(effectiveGenotype); - } - case UNAFFECTED -> { - return checkUnaffected(effectiveGenotype); - } - case MISSING -> { - return POTENTIAL; - } - default -> throw new IllegalArgumentException(); - } - } - - protected MatchEnum checkUnaffected(EffectiveGenotype effectiveGenotype) { - if (effectiveGenotype.getPloidy() == 1) { - return checkUnaffectedHaploid(effectiveGenotype); - } else if (effectiveGenotype.getPloidy() == 2) { - return checkUnaffectedDiploid(effectiveGenotype); - } else if (effectiveGenotype.isCalled()) { - throw new UnsupportedOperationException(String.format("Incompatible ploidy '%s' for haploid check''", effectiveGenotype.getPloidy())); - } - return POTENTIAL; - } - - protected MatchEnum checkUnaffectedDiploid(EffectiveGenotype effectiveGenotype) { - if (effectiveGenotype.hasAltAllele()|| effectiveGenotype.isMixed()) { - return effectiveGenotype.isHom() ? FALSE : POTENTIAL; - } else { - return effectiveGenotype.isHomRef() ? TRUE : POTENTIAL; - } - } - - protected MatchEnum checkUnaffectedHaploid(EffectiveGenotype effectiveGenotype) { - if (effectiveGenotype.isNoCall()) { - return POTENTIAL; - } - if (effectiveGenotype.hasAltAllele()) { - return FALSE; - } - return TRUE; - } - - protected MatchEnum checkAffected(EffectiveGenotype effectiveGenotype) { - if (effectiveGenotype.getPloidy() == 1) { - return checkAffectedHaploid(effectiveGenotype); - } - else if (effectiveGenotype.getPloidy() == 2) { - return checkAffectedDiploid(effectiveGenotype); - } else if (effectiveGenotype.isCalled()) { - throw new UnsupportedOperationException(String.format("Incompatible ploidy '%s' for YL check", effectiveGenotype.getPloidy())); - } - return POTENTIAL; - } - - protected MatchEnum checkAffectedDiploid(EffectiveGenotype effectiveGenotype) { - if (effectiveGenotype.hasAltAllele()) { - return effectiveGenotype.isHom() ? TRUE : POTENTIAL; - } else if (effectiveGenotype.isNoCall() || effectiveGenotype.isMixed()) { - return POTENTIAL; - } else { - return effectiveGenotype.isHomRef() ? FALSE : POTENTIAL; - } - } - - protected MatchEnum checkAffectedHaploid(EffectiveGenotype effectiveGenotype) { - if (effectiveGenotype.isNoCall()) { - return POTENTIAL; - } - if (effectiveGenotype.hasAltAllele()) { - return TRUE; - } - return FALSE; - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java index ad7e875..905618a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -12,10 +12,10 @@ public abstract class InheritanceChecker { - public MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { + public MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { Set results = new HashSet<>(); for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, vcfRecord)); + results.add(checkSample(sample, variantGeneRecord)); } if(results.contains(FALSE)){ return FALSE; @@ -25,5 +25,7 @@ public MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { return TRUE; } - abstract MatchEnum checkSample(Sample sample, VcfRecord vcfRecord); + abstract MatchEnum checkSample(Sample sample, VariantGeneRecord variantGeneRecord); + + } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java index 1941804..bb810aa 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java @@ -1,20 +1,108 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.VariantContext; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import htsjdk.variant.variantcontext.Allele; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; +import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; +import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeMt; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; @Component -public class MtChecker extends HaploidChecker { - public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { - if (!onChromosomeMt(vcfRecord)) { +public class MtChecker { + public MatchEnum check( + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!VariantContextUtils.onChromosomeMt(variantGeneRecord)) { + return FALSE; + } + + return checkFamily(variantGeneRecord, family); + } + + private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + Set affectedAltAlleles = new HashSet<>(); + affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); + if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { + matches.add(POTENTIAL); + } + return merge(matches); + } + + private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if (genotype.isHomRef() || (genotype.getPloidy() == 1 && genotype.hasReference())) { + matches.add(TRUE); + } + else { + if (genotype.getAlleles().stream().allMatch( + allele -> allele.isCalled() && affectedAlleles.contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); + } + } + } + return merge(matches); + } + + private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + affectedGenotypes.add(genotype); + if (!genotype.hasAlt() && genotype.isCalled()) { + return FALSE; + } else if (genotype.isNoCall() || (genotype.isMixed())) { + matches.add(POTENTIAL); + } else { + matches.add(TRUE); + } + } + return merge(matches); + } + + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { return FALSE; + } else if (matches.contains(POTENTIAL)) { + return POTENTIAL; + } + return TRUE; + } + + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); + } } - return checkFamily(vcfRecord, family); + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java index a24bdee..9e90930 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java @@ -2,33 +2,19 @@ import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeX; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.utils.sample.model.Sex.FEMALE; -import static org.molgenis.vcf.utils.sample.model.Sex.MALE; -; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; + +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; -import org.molgenis.vcf.utils.sample.model.Sex; -public abstract class XlChecker extends InheritanceChecker{ +public abstract class XlChecker{ - public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { - if (!onChromosomeX(vcfRecord)) { + public MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!onChromosomeX(variantGeneRecord)) { return FALSE; } - return checkFamily(vcfRecord, family); + return checkFamily(variantGeneRecord, family); } - protected Sex getSex(Sex sex, EffectiveGenotype genotype) { - if (sex == Sex.UNKNOWN) { - //UNKNOWN? use best guess based on number of alleles - if (genotype.getAlleles().size() == 1) { - return MALE; - } else { - return FEMALE; - } - } - return sex; - } + protected abstract MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index 2128f56..2df1f70 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -1,67 +1,98 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; +import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; +import java.util.*; + import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; @Component public class XldChecker extends XlChecker { - protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - EffectiveGenotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - if (effectiveGenotype == null || !effectiveGenotype.isCalled()) { - return POTENTIAL; + public MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ + matches.add(POTENTIAL); } + return merge(matches); + } - switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> { - return checkAffected(effectiveGenotype); + private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if(genotype == null){ + matches.add(POTENTIAL); } - case UNAFFECTED -> { - return checkUnaffected(sample, effectiveGenotype); + else if(!genotype.hasAlt() && !genotype.isMixed() || (genotype.hasReference() && genotype.getPloidy() == 2)){ + matches.add(TRUE); } - case MISSING -> { - return POTENTIAL; + else { + for (EffectiveGenotype affectedGenotype : affectedGenotypes) { + if (affectedGenotype.hasAlt() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( + allele -> genotype.getAlleles().contains(allele))) { + matches.add(FALSE); + } else{ + matches.add(POTENTIAL); + } + } } - default -> throw new IllegalArgumentException(); } + return merge(matches); } - private MatchEnum checkUnaffected(Sample sample, EffectiveGenotype effectiveGenotype) { - switch (getSex(sample.getPerson().getSex(), effectiveGenotype)) { - case MALE -> { - // Healthy males cannot carry the variant - if (effectiveGenotype.getAlleles().stream() - .allMatch(Allele::isReference)) { - return TRUE; - } else if (effectiveGenotype.hasAltAllele()) { - return FALSE; - } - return POTENTIAL; - } - case FEMALE -> { - // Healthy females can carry the variant (because of X inactivation) - if (effectiveGenotype.isMixed() && effectiveGenotype.hasAltAllele()) { - return POTENTIAL; - } - return (effectiveGenotype.isHet() || effectiveGenotype.isMixed() || effectiveGenotype.isHomRef()) ? TRUE : FALSE; + private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + affectedGenotypes.add(genotype); + if (!genotype.hasAlt() && !genotype.isMixed()) { + return FALSE; + } else if ((genotype.hasMissingAllele() && genotype.hasReference()) || genotype.isNoCall()) { + matches.add(POTENTIAL); + } else { + matches.add(TRUE); } - default -> throw new IllegalArgumentException(); } + return merge(matches); + } + + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { + return FALSE; + } else if (matches.contains(POTENTIAL)) { + return POTENTIAL; + } + return TRUE; } - private static MatchEnum checkAffected(EffectiveGenotype effectiveGenotype) { - // Affected individuals have to be het. or hom. alt. - if (effectiveGenotype.hasAltAllele()) { - return TRUE; - } else { - //homRef? then XLD==false, is any allele is missing than the match is "potential" - return effectiveGenotype.isHomRef() ? FALSE : POTENTIAL; + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); + } } + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index cee5c1c..9b171df 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -1,81 +1,93 @@ package org.molgenis.vcf.inheritance.matcher.checker; +import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; +import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; +import java.util.*; + import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; @Component public class XlrChecker extends XlChecker { - protected MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { - EffectiveGenotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); - if (effectiveGenotype == null || !effectiveGenotype.isCalled()) { + protected MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + Set affectedAltAlleles = new HashSet<>(); + affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); + if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { + matches.add(POTENTIAL); + } + return merge(matches); + } + + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { + return FALSE; + } else if (matches.contains(POTENTIAL)) { return POTENTIAL; } + return TRUE; + } - switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> { - return checkAffected(sample, effectiveGenotype); + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); } - case UNAFFECTED -> { - return checkUnaffected(sample, effectiveGenotype); - } - case MISSING -> { - return POTENTIAL; - } - default -> throw new IllegalArgumentException(); } + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; } - private MatchEnum checkUnaffected(Sample sample, EffectiveGenotype effectiveGenotype) { - switch (getSex(sample.getPerson().getSex(), effectiveGenotype)) { - case MALE -> { - // Healthy males cannot carry the variant. - if (effectiveGenotype.hasAltAllele()) { - return FALSE; - } else if (effectiveGenotype.isHomRef()) { - return TRUE; - } - return null; + private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if (genotype != null && genotype.hasReference()) { + matches.add(TRUE); + } else if (genotype != null && genotype.getAlleles().stream().allMatch( + allele -> allele.isCalled() && affectedAlleles.contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); } - case FEMALE -> { - // Healthy females cannot be hom. alt. - if (effectiveGenotype.hasAltAllele() && effectiveGenotype.isHom()) { - return FALSE; - } else if (effectiveGenotype.hasAltAllele() && effectiveGenotype.isMixed()) { - return POTENTIAL; - } - return TRUE; - } - default -> throw new IllegalArgumentException(); } + return merge(matches); } - private MatchEnum checkAffected(Sample sample, EffectiveGenotype effectiveGenotype) { - switch (getSex(sample.getPerson().getSex(), effectiveGenotype)) { - case MALE -> { - // Affected males have to be het. or hom. alt. (het is theoretically not possible in males, but can occur due to Pseudo Autosomal Regions). - if (effectiveGenotype.hasAltAllele()) { - return TRUE; - } else if (effectiveGenotype.isMixed()) { - return POTENTIAL; - } + private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + affectedGenotypes.add(genotype); + if (genotype.hasReference()) { return FALSE; + } else if ((genotype.hasMissingAllele()) || genotype.isNoCall()) { + matches.add(POTENTIAL); + } else { + matches.add(TRUE); } - case FEMALE -> { - // Affected females have to be hom. alt. - if (effectiveGenotype.isHomRef()) { - return FALSE; - } else if (effectiveGenotype.hasAltAllele() && effectiveGenotype.isMixed()) { - return POTENTIAL; - } - return effectiveGenotype.isHom() ? TRUE : FALSE; - } - default -> throw new IllegalArgumentException(); } + return merge(matches); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java index ab34d0d..b5537d8 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java @@ -1,43 +1,130 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import htsjdk.variant.variantcontext.Allele; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; +import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import org.molgenis.vcf.utils.sample.model.Sex; import org.springframework.stereotype.Component; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeY; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; +import static org.molgenis.vcf.utils.sample.model.Sex.FEMALE; +import static org.molgenis.vcf.utils.sample.model.Sex.MALE; @Component -public class YlChecker extends HaploidChecker{ - public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { - if (!onChromosomeY(vcfRecord)) { +public class YlChecker { + public MatchEnum check( + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!VariantContextUtils.onChromosomeY(variantGeneRecord)) { return FALSE; } - return checkFamily(vcfRecord, family); + + return checkFamily(variantGeneRecord, family); } - @Override - public MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { - Set results = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getSex() == Sex.FEMALE) { - //female familty members do not play a role in Y-linked inheritance - results.add(TRUE); + private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + Set affectedAltAlleles = new HashSet<>(); + affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); + if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { + matches.add(POTENTIAL); + } + return merge(matches); + } + + private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + Set matches = new HashSet<>(); + for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if(getSex(unAffectedSample, genotype) == FEMALE){ + matches.add(TRUE); + } else if (genotype.isHomRef() || (genotype.getPloidy() == 1 && genotype.hasReference())) { + matches.add(TRUE); + } + else { + if (genotype.getAlleles().stream().allMatch( + allele -> allele.isCalled() && affectedAlleles.contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); + } + } + } + return merge(matches); + } + + private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + Set matches = new HashSet<>(); + for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { + EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + if(getSex(affectedSample, genotype) == FEMALE){ + return FALSE; + } + affectedGenotypes.add(genotype); + if (!genotype.hasAlt() && genotype.isCalled()) { + return FALSE; + } else if (genotype.isNoCall() || (genotype.isMixed())) { + matches.add(POTENTIAL); } else { - results.add(checkSample(sample, vcfRecord)); + matches.add(TRUE); } } - if (results.contains(FALSE)) { + return merge(matches); + } + + private static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { return FALSE; - } else if (results.contains(POTENTIAL)) { + } else if (matches.contains(POTENTIAL)) { return POTENTIAL; } return TRUE; } + + private Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); + } + } + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; + } + + protected static Sex getSex(Sample sample, EffectiveGenotype genotype) { + if (sample.getPerson().getSex() == Sex.UNKNOWN) { + //UNKNOWN? use best guess based on number of alleles + if (genotype.getAlleles().size() == 1) { + return MALE; + } else { + return FEMALE; + } + }else{ + return sample.getPerson().getSex(); + } + } + } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Annotation.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Annotation.java deleted file mode 100644 index 2176204..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Annotation.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher.model; - -import java.util.Set; -import lombok.Builder; -import lombok.Data; -import lombok.NonNull; -import lombok.experimental.NonFinal; - -@Data -@Builder -@NonFinal -public class Annotation { - - @NonNull - Inheritance inheritance; - Set matchingGenes; -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java index 24c0dd8..b185632 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java @@ -1,12 +1,11 @@ package org.molgenis.vcf.inheritance.matcher.model; -import htsjdk.variant.variantcontext.VariantContext; import lombok.Builder; import lombok.Value; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; @Value @Builder public class CompoundCheckResult { - VcfRecord possibleCompound; + VariantGeneRecord possibleCompound; boolean isCertain; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Gene.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Gene.java deleted file mode 100644 index 9b98a7f..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Gene.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher.model; - -import java.util.Set; -import lombok.Value; - -@Value -public class Gene { - - String id; - String symbolSource; - Set inheritanceModes; -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java new file mode 100644 index 0000000..c05c5e9 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java @@ -0,0 +1,6 @@ +package org.molgenis.vcf.inheritance.matcher.model; + +import java.util.Set; + +public record GeneInfo(String geneId, String symbolSource, Set inheritanceModes) { +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Inheritance.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Inheritance.java deleted file mode 100644 index 2e9165c..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/Inheritance.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher.model; - -import java.util.HashSet; -import java.util.Set; -import lombok.Builder; -import lombok.Data; - -@Data -@Builder -public class Inheritance { - @Builder.Default - Set pedigreeInheritanceMatches = new HashSet<>(); - @Builder.Default - Set compounds = new HashSet<>(); - - @Builder.Default - MatchEnum match = MatchEnum.POTENTIAL; - - @Builder.Default - MatchEnum denovo = MatchEnum.POTENTIAL; - - public void addInheritanceMode(PedigreeInheritanceMatch pedigreeInheritanceMatch) { - pedigreeInheritanceMatches.add(pedigreeInheritanceMatch); - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java new file mode 100644 index 0000000..3fd4bc2 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java @@ -0,0 +1,81 @@ +package org.molgenis.vcf.inheritance.matcher.model; + +import lombok.Builder; +import lombok.Data; +import lombok.NonNull; +import org.molgenis.vcf.utils.UnexpectedEnumException; + +import java.util.HashSet; +import java.util.Set; + +import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; +import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; + +@Data +@Builder +public class InheritanceGeneResult { + + @NonNull + GeneInfo geneInfo; + @Builder.Default + Set pedigreeInheritanceMatches = new HashSet<>(); + @Builder.Default + Set compounds = new HashSet<>(); + + public void addInheritanceMode(PedigreeInheritanceMatch pedigreeInheritanceMatch) { + pedigreeInheritanceMatches.add(pedigreeInheritanceMatch); + } + + /** + * If there is a match between sample inheritance modes and gene inheritance modes: + * - inheritance match is true + * If there are no matches between sample inheritance modes and gene inheritance modes: + * - inheritance match is unknown ifa gene has unknown inheritance pattern. + * - inheritance match is false if a gene has known (but mismatching) inheritance pattern. + */ + public MatchEnum getMatch() { + //If no inheritance pattern is suitable for the sample, regardless of the gene: inheritance match is false. + if(pedigreeInheritanceMatches.isEmpty()){ + return FALSE; + } + boolean containsUnknownGene = false; + + Set geneInheritanceModes = geneInfo + .inheritanceModes(); + if( geneInheritanceModes.isEmpty() ){ + containsUnknownGene = true; + } + if (geneInheritanceModes.stream() + .anyMatch(geneInheritanceMode -> isMatch(pedigreeInheritanceMatches, geneInheritanceMode))) { + if(pedigreeInheritanceMatches.stream().anyMatch(pedigreeInheritanceMatch -> !pedigreeInheritanceMatch.isUncertain())){ + return TRUE; + }else { + return POTENTIAL; + } + } + return containsUnknownGene? POTENTIAL : FALSE; + } + private static Boolean isMatch(Set pedigreeInheritanceMatches, InheritanceMode geneInheritanceMode) { + for(PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { + switch (pedigreeInheritanceMatch.inheritanceMode()) { + case AD, AD_IP -> { + if (geneInheritanceMode == AD) { + return true; + } + } + case AR, AR_C -> { + if (geneInheritanceMode == AR) { + return true; + } + } + case XLR, XLD -> { + if (geneInheritanceMode == XL) { + return true; + } + } + default -> throw new UnexpectedEnumException(pedigreeInheritanceMatch.inheritanceMode()); + } + } + return false; + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java new file mode 100644 index 0000000..9a7ce60 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java @@ -0,0 +1,16 @@ +package org.molgenis.vcf.inheritance.matcher.model; + +import java.util.*; + +import lombok.Builder; +import lombok.Data; +import org.molgenis.vcf.utils.sample.model.Sample; + +@Data +@Builder +public class InheritanceResult { + + @Builder.Default + Collection inheritanceGeneResults = new HashSet<>(); + Map denovo; +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/PedigreeInheritanceMatch.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/PedigreeInheritanceMatch.java index 574e5f9..aac8911 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/PedigreeInheritanceMatch.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/PedigreeInheritanceMatch.java @@ -1,9 +1,4 @@ package org.molgenis.vcf.inheritance.matcher.model; -import lombok.Value; - -@Value -public class PedigreeInheritanceMatch { - InheritanceMode inheritanceMode; - boolean isUncertain; +public record PedigreeInheritanceMatch(InheritanceMode inheritanceMode, boolean isUncertain) { } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java index 3b0f24d..fbc5b70 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java @@ -6,7 +6,7 @@ @Data @Builder public class VcfRecordGenes { - Map genes; + Map genes; //FIXME: is this used? @Builder.Default boolean containsVcWithoutGene = false; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java index 41446f9..6d4f884 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactory.java @@ -1,9 +1,8 @@ package org.molgenis.vcf.inheritance.matcher.util; import org.molgenis.vcf.inheritance.matcher.InheritanceService; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.Settings; public interface InheritanceServiceFactory { - InheritanceService create(Settings settings, VepMetadata vepMetadata); + InheritanceService create(Settings settings); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java index c69a162..102cd3b 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImpl.java @@ -20,7 +20,7 @@ public InheritanceServiceFactoryImpl(Annotator annotator, PedigreeInheritanceChe } @Override - public InheritanceService create(Settings settings, VepMetadata vepMetadata) { - return new InheritanceService(annotator, vepMetadata, pedigreeInheritanceChecker, settings.getInputPedPaths(), settings.getProbands()); + public InheritanceService create(Settings settings) { + return new InheritanceService(annotator, pedigreeInheritanceChecker, settings.getInputPedPaths(), settings.getProbands()); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java index 512e2aa..e95e20a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java @@ -17,8 +17,4 @@ public static boolean hasMissing(Genotype genotype) { return genotype == null || genotype.getAlleles().stream() .anyMatch(Allele::isNoCall); } - - public static boolean isAlt(Allele allele) { - return allele.isCalled() && allele.isNonReference(); - } } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java deleted file mode 100644 index 0e0bf68..0000000 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AnnotatorTest.java +++ /dev/null @@ -1,228 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import static java.util.Collections.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; -import static org.molgenis.vcf.inheritance.matcher.Annotator.DENOVO; -import static org.molgenis.vcf.inheritance.matcher.Annotator.INHERITANCE_MATCH; -import static org.molgenis.vcf.inheritance.matcher.Annotator.INHERITANCE_MODES; -import static org.molgenis.vcf.inheritance.matcher.Annotator.MATCHING_GENES; -import static org.molgenis.vcf.inheritance.matcher.Annotator.POSSIBLE_COMPOUND; -import static org.molgenis.vcf.inheritance.matcher.checker.PedigreeTestUtil.createFamily; -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.FALSE; -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.TRUE; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; -import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.createGenotype; - -import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; -import htsjdk.variant.variantcontext.VariantContextBuilder; -import htsjdk.variant.vcf.VCFFormatHeaderLine; -import htsjdk.variant.vcf.VCFHeader; -import htsjdk.variant.vcf.VCFHeaderLineCount; -import htsjdk.variant.vcf.VCFHeaderLineType; -import htsjdk.variant.vcf.VCFInfoHeaderLine; -import java.util.Map; -import java.util.Set; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.model.Annotation; -import org.molgenis.vcf.inheritance.matcher.model.Inheritance; -import org.molgenis.vcf.inheritance.matcher.model.PedigreeInheritanceMatch; -import org.molgenis.vcf.utils.sample.model.AffectedStatus; -import org.molgenis.vcf.utils.sample.model.Pedigree; -import org.molgenis.vcf.utils.sample.model.Sex; - -@ExtendWith(MockitoExtension.class) -class AnnotatorTest { - - private Annotator annotator; - - @Mock - VepMetadata vepMetadata; - - @BeforeEach - void setUp() { - annotator = new Annotator(); - } - - @Test - void annotateHeader() { - VCFHeader vcfHeader = mock(VCFHeader.class); - annotator.annotateHeader(vcfHeader); - assertAll( - () -> verify(vcfHeader) - .addMetaDataLine( - new VCFFormatHeaderLine(INHERITANCE_MODES, VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "An enumeration of possible inheritance modes based on the pedigree of the sample. Potential values: AD, AD_IP, AR, AR_C, XLR, XLD")), - () -> verify(vcfHeader).addMetaDataLine(new VCFFormatHeaderLine(POSSIBLE_COMPOUND, 1, - VCFHeaderLineType.String, - "Possible Compound hetrozygote variants.")), - () -> verify(vcfHeader).addMetaDataLine(new VCFFormatHeaderLine(DENOVO, 1, - VCFHeaderLineType.Integer, - "De novo variant.")), - () -> verify(vcfHeader).addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MATCH, 1, - VCFHeaderLineType.Integer, - "Inheritance Match: Genotypes, affected statuses and known gene inheritance patterns match.")), - () -> verify(vcfHeader) - .addMetaDataLine(new VCFFormatHeaderLine(MATCHING_GENES, VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "Genes with a (potential) inheritance match.")), - () -> verify(vcfHeader, times(2)).getInfoHeaderLines(), - () -> verify(vcfHeader, times(2)).getFormatHeaderLines(), - () -> verify(vcfHeader, times(2)).getFilterLines(), - () -> verify(vcfHeader).getContigLines(), - () -> verify(vcfHeader).getOtherHeaderLines(), - () -> verify(vcfHeader).getGenotypeSamples()); - - verifyNoMoreInteractions(vcfHeader); - } - - @Test - void annotateHeaderEscapedQuotesFormat1() { - VCFHeader vcfHeader = mock(VCFHeader.class); - when(vcfHeader.getFormatHeaderLines()).thenReturn( - Set.of(new VCFFormatHeaderLine("TEST", VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "\"test\""))); - VCFHeader newHeader = annotator.annotateHeader(vcfHeader); - assertEquals(new VCFFormatHeaderLine("TEST", VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "\\\"test\"").toString(), newHeader.getFormatHeaderLine("TEST").toString()); - } - - @Test - void annotateHeaderEscapedQuotesFormat2() { - VCFHeader vcfHeader = mock(VCFHeader.class); - when(vcfHeader.getFormatHeaderLines()).thenReturn( - Set.of(new VCFFormatHeaderLine("TEST", 1, - VCFHeaderLineType.String, - "\"test\""))); - VCFHeader newHeader = annotator.annotateHeader(vcfHeader); - assertEquals(new VCFFormatHeaderLine("TEST", 1, - VCFHeaderLineType.String, - "\\\"test\"").toString(), newHeader.getFormatHeaderLine("TEST").toString()); - } - - @Test - void annotateHeaderEscapedQuotesInfo1() { - VCFHeader vcfHeader = mock(VCFHeader.class); - when(vcfHeader.getInfoHeaderLines()).thenReturn( - Set.of(new VCFInfoHeaderLine("TEST", VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "\"test\""))); - VCFHeader newHeader = annotator.annotateHeader(vcfHeader); - assertEquals(new VCFInfoHeaderLine("TEST", VCFHeaderLineCount.UNBOUNDED, - VCFHeaderLineType.String, - "\\\"test\"").toString(), newHeader.getInfoHeaderLine("TEST").toString()); - } - - @Test - void annotateHeaderEscapedQuotesInfo2() { - VCFHeader vcfHeader = mock(VCFHeader.class); - when(vcfHeader.getInfoHeaderLines()).thenReturn( - Set.of(new VCFInfoHeaderLine("TEST", 1, - VCFHeaderLineType.String, - "\"test\""))); - VCFHeader newHeader = annotator.annotateHeader(vcfHeader); - assertEquals(new VCFInfoHeaderLine("TEST", 1, - VCFHeaderLineType.String, - "\\\"test\"").toString(), newHeader.getInfoHeaderLine("TEST").toString()); - } - - @Test - void annotateInheritance() { - Genotype genotype = createGenotype("Patient", "1/1"); - VariantContext vc = new VariantContextBuilder().chr("1").start(1).stop(1).alleles("T", "A") - .genotypes(genotype) - .make(); - Pedigree familyMap = createFamily(Sex.MALE, AffectedStatus.AFFECTED, AffectedStatus.UNAFFECTED, - AffectedStatus.UNAFFECTED, "FAM"); - Map families = Map.of("FAM", familyMap); - - Inheritance inheritance = Inheritance.builder().match(TRUE).denovo(TRUE).pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AD_IP, false), new PedigreeInheritanceMatch(AR_C, false))) - .compounds(singleton("OTHER_VARIANT")).build(); - Annotation annotation = Annotation.builder().inheritance(inheritance).matchingGenes( - Set.of("GENE1", "GENE2")).build(); - Map annotationMap = Map.of("Patient", annotation); - - VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, vepMetadata, emptySet()), families, annotationMap).unwrap(); - - assertAll( - () -> assertEquals("AD_IP,AR_C", - actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MODES)), - () -> assertEquals("1", - actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MATCH)), - () -> assertEquals("GENE1,GENE2", - actual.getGenotype("Patient").getExtendedAttribute(MATCHING_GENES)), - () -> assertEquals("1", actual.getGenotype("Patient").getExtendedAttribute(DENOVO)), - () -> assertEquals("OTHER_VARIANT", - actual.getGenotype("Patient").getExtendedAttribute(POSSIBLE_COMPOUND)) - ); - } - - @Test - void annotateInheritanceMissingGeneInheritancePattern() { - Genotype genotype = createGenotype("Patient", "1/1"); - VariantContext vc = new VariantContextBuilder().chr("1").start(1).stop(1).alleles("T", "A") - .genotypes(genotype) - .make(); - Pedigree familyMap = createFamily(Sex.MALE, AffectedStatus.AFFECTED, AffectedStatus.UNAFFECTED, - AffectedStatus.UNAFFECTED, "FAM"); - Map families = Map.of("FAM", familyMap); - - Inheritance inheritance = Inheritance.builder().denovo(TRUE) - .pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP, false), new PedigreeInheritanceMatch(AR_C, false))) - .compounds(singleton("OTHER_VARIANT")).build(); - Annotation annotation = Annotation.builder().inheritance(inheritance).build(); - Map annotationMap = Map.of("Patient", annotation); - - VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, vepMetadata, emptySet()), families, annotationMap).unwrap(); - - assertAll( - () -> assertEquals("AD_IP,AR_C", - actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MODES)), - () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MATCH)), - () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(MATCHING_GENES)), - () -> assertEquals("1", actual.getGenotype("Patient").getExtendedAttribute(DENOVO)), - () -> assertEquals("OTHER_VARIANT", - actual.getGenotype("Patient").getExtendedAttribute(POSSIBLE_COMPOUND)) - ); - } - - @Test - void annotateInheritanceNoMatch() { - Genotype genotype = createGenotype("Patient", "1/1"); - VariantContext vc = new VariantContextBuilder().chr("1").start(1).stop(1).alleles("T", "A") - .genotypes(genotype) - .make(); - Pedigree familyMap = createFamily(Sex.MALE, AffectedStatus.AFFECTED, AffectedStatus.UNAFFECTED, - AffectedStatus.UNAFFECTED, "FAM"); - Map families = Map.of("FAM", familyMap); - - Inheritance inheritance = Inheritance.builder().match(FALSE).denovo(TRUE).pedigreeInheritanceMatches( - emptySet()) - .compounds(emptySet()).build(); - Annotation annotation = Annotation.builder().inheritance(inheritance).build(); - Map annotationMap = Map.of("Patient", annotation); - - VariantContext actual = annotator.annotateInheritance(new VcfRecord(vc, vepMetadata, emptySet()), families, annotationMap).unwrap(); - - assertAll( - () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MODES)), - () -> assertEquals("0", actual.getGenotype("Patient").getExtendedAttribute(INHERITANCE_MATCH)), - () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(MATCHING_GENES)), - () -> assertEquals("1", actual.getGenotype("Patient").getExtendedAttribute(DENOVO)), - () -> assertNull(actual.getGenotype("Patient").getExtendedAttribute(POSSIBLE_COMPOUND)) - ); - } -} \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java index e968003..e1f37d4 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java @@ -54,7 +54,7 @@ void testProband() throws IOException { String pedigree = ResourceUtils.getFile("classpath:pedigree_complex.ped").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-pc","LP,P"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-pc","P:LP,P;B:LB,B;V:VUS"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java deleted file mode 100644 index 95fe2e8..0000000 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/InheritanceMatcherTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import static java.util.Collections.emptySet; -import static java.util.Collections.singleton; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; - -import java.util.Map; -import java.util.Set; -import org.junit.jupiter.api.Test; -import org.molgenis.vcf.inheritance.matcher.model.*; - -class InheritanceMatcherTest { - - @Test - void matchInheritanceMatch() { - Inheritance inheritance1 = Inheritance.builder().denovo(TRUE).pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false), new PedigreeInheritanceMatch(InheritanceMode.AR_C,false))).compounds(singleton("OTHER_VARIANT")).build(); - Inheritance inheritance2 = Inheritance.builder().denovo(FALSE).pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AR,false))).compounds(singleton("OTHER_VARIANT")).build(); - Map inheritanceMap = Map.of("sample1", inheritance1, "sample2", - inheritance2); - VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", Set.of(AR,AD)), "GENE2", new Gene("GENE2","EntrezGene", Set.of(AD)))).build(); - - Map actual = InheritanceMatcher - .matchInheritance(inheritanceMap, genes); - - Inheritance expectedInheritance1 = Inheritance.builder().match(TRUE).denovo(TRUE).pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false), new PedigreeInheritanceMatch(InheritanceMode.AR_C,false))).compounds(singleton("OTHER_VARIANT")).build(); - Inheritance expectedInheritance2 = Inheritance.builder().match(TRUE).denovo(FALSE).pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AR,false))).compounds(singleton("OTHER_VARIANT")).build(); - Annotation annotation1 = Annotation.builder().inheritance(expectedInheritance1).matchingGenes(Set.of("GENE1","GENE2")).build(); - Annotation annotation2 = Annotation.builder().inheritance(expectedInheritance2).matchingGenes(Set.of("GENE1")).build(); - Map expected = Map.of("sample1",annotation1,"sample2",annotation2); - assertEquals(expected, actual); - } - - @Test - void matchInheritanceMismatch() { - Inheritance inheritance = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false))).build(); - Map inheritanceMap = Map.of("sample1", inheritance); - VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", Set.of(AR)))).build(); - - Map actual = InheritanceMatcher - .matchInheritance(inheritanceMap, genes); - - Inheritance expectedInheritance = Inheritance.builder().match(FALSE).pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AD_IP, false))).compounds(emptySet()).build(); - Annotation expectedAnnotation = Annotation.builder().inheritance(expectedInheritance).matchingGenes(emptySet()).build(); - Map expected = Map.of("sample1",expectedAnnotation); - - assertEquals(expected, actual); - } - - @Test - void matchInheritanceNoSuitableModes() { - Inheritance inheritance1 = Inheritance.builder().match(FALSE).pedigreeInheritanceMatches( - emptySet()).pedigreeInheritanceMatches(emptySet()).build(); - Map inheritanceMap = Map.of("sample1", inheritance1); - VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", Set.of(AR,AD)),"GENE2",new Gene("GENE2","EntrezGene", Set.of(AD)))).build(); - - Map actual = InheritanceMatcher - .matchInheritance(inheritanceMap, genes); - - Inheritance expectedInheritance = Inheritance.builder().match(FALSE).pedigreeInheritanceMatches( - emptySet()).pedigreeInheritanceMatches(emptySet()).compounds(emptySet()).build(); - Annotation expectedAnnotation = Annotation.builder().inheritance(expectedInheritance).matchingGenes(emptySet()).build(); - Map expected = Map.of("sample1",expectedAnnotation); - assertEquals(expected, actual); - } - - @Test - void matchInheritanceUnknownGene() { - Inheritance inheritance1 = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false), new PedigreeInheritanceMatch(InheritanceMode.AR_C,false))).compounds(singleton("OTHER_VARIANT")).build(); - Map inheritanceMap = Map.of("sample1", inheritance1); - VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", emptySet()))).build(); - - Map actual = InheritanceMatcher - .matchInheritance(inheritanceMap, genes); - - Inheritance expectedInheritance = Inheritance.builder().match(POTENTIAL).pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(AD_IP,false), new PedigreeInheritanceMatch(InheritanceMode.AR_C,false))).compounds(singleton("OTHER_VARIANT")).build(); - Annotation expectedAnnotation = Annotation.builder().inheritance(expectedInheritance).matchingGenes(emptySet()).build(); - Map expected = Map.of("sample1",expectedAnnotation); - assertEquals(expected, actual); - } - - @Test - void matchInheritanceUnknownGeneAndKnownGeneMatch() { - Inheritance inheritance1 = Inheritance.builder().pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AR_C, false))).compounds(singleton("OTHER_VARIANT")).build(); - Map inheritanceMap = Map.of("sample1", inheritance1); - VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1",new Gene("GENE1","EntrezGene", emptySet()),"GENE2",new Gene("GENE2","EntrezGene", Set.of(AR)))).build(); - - Map actual = InheritanceMatcher - .matchInheritance(inheritanceMap, genes); - - Inheritance expectedInheritance = Inheritance.builder().match(TRUE).pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.AR_C,false))).compounds(singleton("OTHER_VARIANT")).build(); - Annotation expectedAnnotation = Annotation.builder().inheritance(expectedInheritance).matchingGenes(Set.of("GENE2")).build(); - Map expected = Map.of("sample1",expectedAnnotation); - assertEquals(expected, actual); - } - - @Test - void matchInheritanceUnknownGeneAndKnownGeneMismatch() { - Inheritance inheritance1 = Inheritance.builder().pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AD,false))).compounds(emptySet()).build(); - - Map inheritanceMap = Map.of("sample1", inheritance1); - VcfRecordGenes genes = VcfRecordGenes.builder().genes(Map.of("GENE1", new Gene("GENE1","EntrezGene", emptySet()),"GENE2", - new Gene("GENE2","EntrezGene", Set.of(AR)))).build(); - - Map actual = InheritanceMatcher - .matchInheritance(inheritanceMap, genes); - - Inheritance expectedInheritance = Inheritance.builder().match(POTENTIAL).pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(AD,false))).compounds(emptySet()).build(); - Annotation expectedAnnotation = Annotation.builder().inheritance(expectedInheritance).matchingGenes(emptySet()).build(); - Map expected = Map.of("sample1",expectedAnnotation); - assertEquals(expected, actual); - } -} \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java index f2ad31c..c5c0f1f 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java @@ -8,18 +8,11 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.checker.*; -import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; -import org.molgenis.vcf.inheritance.matcher.model.Inheritance; -import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; -import org.molgenis.vcf.inheritance.matcher.model.PedigreeInheritanceMatch; +import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.utils.sample.model.Pedigree; -import org.molgenis.vcf.utils.sample.model.Sample; -import java.util.List; -import java.util.Map; import java.util.Set; -import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -42,195 +35,81 @@ class PedigreeInheritanceCheckerTest { YlChecker ylChecker; @Mock MtChecker mtChecker; - @Mock - DeNovoChecker deNovoChecker; - @Mock - VepMetadata vepMetadata; private PedigreeInheritanceChecker pedigreeInheritanceChecker; @BeforeEach void setUp() { - pedigreeInheritanceChecker = new PedigreeInheritanceChecker(xldChecker, xlrChecker, adChecker, adNonPenetranceChecker, arChecker, ylChecker, mtChecker, deNovoChecker); + pedigreeInheritanceChecker = new PedigreeInheritanceChecker(xldChecker, xlrChecker, adChecker, adNonPenetranceChecker, arChecker, ylChecker, mtChecker); } @Test - void testAdIpPotential() { + void testAdPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(record, family)).thenReturn(FALSE); - when(xlrChecker.check(record, family)).thenReturn(FALSE); - when(adChecker.check(record, family)).thenReturn(FALSE); - when(arChecker.check(record, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(POTENTIAL); - when(mtChecker.check(record, family)).thenReturn(FALSE); - when(ylChecker.check(record, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.AD_IP, true))).denovo(FALSE).build(); - - assertEquals(expected, actual); + when(adChecker.check(record, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.AD); + assertEquals(POTENTIAL, actual); } @Test - void testXlRDTrue() { + void testAdIpTrue() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(record, family)).thenReturn(TRUE); - when(xlrChecker.check(record, family)).thenReturn(TRUE); - when(adChecker.check(record, family)).thenReturn(FALSE); - when(arChecker.check(record, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(record, family)).thenReturn(FALSE); - when(ylChecker.check(record, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(InheritanceMode.XLD, false), - new PedigreeInheritanceMatch(InheritanceMode.XLR, false))).denovo(FALSE).build(); - - assertEquals(expected, actual); + when(adNonPenetranceChecker.check(record, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.AD_IP); + assertEquals(TRUE, actual); } @Test - void testArAdMixed() { + void testArPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(record, family)).thenReturn(FALSE); - when(xlrChecker.check(record, family)).thenReturn(FALSE); - when(adChecker.check(record, family)).thenReturn(TRUE); when(arChecker.check(record, family)).thenReturn(POTENTIAL); - when(mtChecker.check(record, family)).thenReturn(FALSE); - when(ylChecker.check(record, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(InheritanceMode.AD, false), - new PedigreeInheritanceMatch(InheritanceMode.AR, true))).denovo(FALSE).build(); - - assertEquals(expected, actual); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.AR); + assertEquals(POTENTIAL, actual); } @Test - void testAdDenovoMixed() { + void testXldFalse() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); when(xldChecker.check(record, family)).thenReturn(FALSE); - when(xlrChecker.check(record, family)).thenReturn(FALSE); - when(adChecker.check(record, family)).thenReturn(TRUE); - when(arChecker.check(record, family)).thenReturn(FALSE); - when(mtChecker.check(record, family)).thenReturn(FALSE); - when(ylChecker.check(record, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(TRUE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches( - Set.of(new PedigreeInheritanceMatch(InheritanceMode.AD, false))).denovo(TRUE).build(); - - assertEquals(expected, actual); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.XLD); + assertEquals(FALSE, actual); } @Test - void testArPotential() { + void testXlrPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); - VariantContext vc2 = mock(VariantContext.class); - Allele ref = mock(Allele.class); - when(ref.getBaseString()).thenReturn("A"); - Allele alt = mock(Allele.class); - when(alt.getBaseString()).thenReturn("T"); - when(vc2.getContig()).thenReturn("chr1"); - when(vc2.getStart()).thenReturn(123); - when(vc2.getReference()).thenReturn(ref); - when(vc2.getAlternateAlleles()).thenReturn(List.of(alt)); - VcfRecord record2 = new VcfRecord(vc2, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(record, family)).thenReturn(FALSE); - when(xlrChecker.check(record, family)).thenReturn(FALSE); - when(adChecker.check(record, family)).thenReturn(FALSE); - when(arChecker.check(record, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(record, family)).thenReturn(FALSE); - when(ylChecker.check(record, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(List.of(CompoundCheckResult.builder().possibleCompound(record2).isCertain(false).build())); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.AR_C, true))).compounds(Set.of("chr1_123_A_T")).denovo(FALSE).build(); - - assertEquals(expected, actual); + when(xlrChecker.check(record, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.XLR); + assertEquals(POTENTIAL, actual); } @Test - void testMtPotential() { + void testYlTrue() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(record, family)).thenReturn(FALSE); - when(xlrChecker.check(record, family)).thenReturn(FALSE); - when(adChecker.check(record, family)).thenReturn(FALSE); - when(arChecker.check(record, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(record, family)).thenReturn(POTENTIAL); - when(ylChecker.check(record, family)).thenReturn(FALSE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(FALSE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.MT, true))).denovo(FALSE).build(); - - assertEquals(expected, actual); + when(ylChecker.check(record, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.YL); + assertEquals(TRUE, actual); } @Test - void testYl() { + void testMtPotential() { VariantContext vc = mock(VariantContext.class); - VcfRecord record = new VcfRecord(vc, vepMetadata, emptySet()); + VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - Sample sample = mock(Sample.class); - ArCompoundChecker arCompoundChecker = mock(ArCompoundChecker.class); - when(xldChecker.check(record, family)).thenReturn(FALSE); - when(xlrChecker.check(record, family)).thenReturn(FALSE); - when(adChecker.check(record, family)).thenReturn(FALSE); - when(arChecker.check(record, family)).thenReturn(FALSE); - when(adNonPenetranceChecker.check(record, family, FALSE)).thenReturn(FALSE); - when(mtChecker.check(record, family)).thenReturn(FALSE); - when(ylChecker.check(record, family)).thenReturn(TRUE); - when(deNovoChecker.checkDeNovo(record, sample)).thenReturn(TRUE); - Map> geneMap = emptyMap(); - when(arCompoundChecker.check(geneMap, record, family, FALSE)).thenReturn(emptyList()); - - Inheritance actual = pedigreeInheritanceChecker.calculatePedigreeInheritance(geneMap, record, sample, family, arCompoundChecker); - Inheritance expected = Inheritance.builder().pedigreeInheritanceMatches(Set.of(new PedigreeInheritanceMatch(InheritanceMode.YL, false))).denovo(TRUE).build(); - - assertEquals(expected, actual); + when(mtChecker.check(record, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.MT); + assertEquals(POTENTIAL, actual); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java index 1a1a710..69cc48c 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.when; -import htsjdk.variant.variantcontext.VariantContext; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -14,7 +13,7 @@ class VariantContextUtilsTest { @Mock - private VcfRecord variantContext; + private VariantGeneRecord variantContext; @Test void onAutosomeTrue() { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java deleted file mode 100644 index 67c9546..0000000 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VepMetadataTest.java +++ /dev/null @@ -1,115 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import static java.util.Collections.emptySet; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.AR; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.AD; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.XLD; -import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.XLR; - -import htsjdk.variant.variantcontext.VariantContext; -import htsjdk.variant.vcf.VCFHeader; -import htsjdk.variant.vcf.VCFInfoHeaderLine; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.model.Gene; -import org.molgenis.vcf.inheritance.matcher.model.VcfRecordGenes; -import org.molgenis.vcf.utils.metadata.FieldMetadataService; -import org.molgenis.vcf.utils.model.FieldMetadata; -import org.molgenis.vcf.utils.model.NestedField; -import org.molgenis.vcf.utils.model.NumberType; - -@ExtendWith(MockitoExtension.class) -class VepMetadataTest { - - @Mock - VariantContext vc; - @Mock - FieldMetadataService fieldMetadataService; - - private VepMetadata vepMetadata; - - @BeforeEach - void setUp() { - VcfReader vcfReader = mock(VcfReader.class); - VCFHeader header = mock(VCFHeader.class); - VCFInfoHeaderLine infoHeader = mock(VCFInfoHeaderLine.class); - when(infoHeader.getID()).thenReturn("CSQ"); - when(infoHeader.getDescription()).thenReturn( - "Consequence annotations from Ensembl VEP. Format: Allele|Consequence|IMPACT|SYMBOL|Gene|Feature_type|Feature|BIOTYPE|EXON|INTRON|HGVSc|HGVSp|cDNA_position|CDS_position|Protein_position|Amino_acids|Codons|Existing_variation|DISTANCE|STRAND|FLAGS|SYMBOL_SOURCE|HGNC_ID|HGVS_OFFSET|InheritanceModesGene|InheritanceModesPheno|PREFERRED"); - HashMap vepMeta = new HashMap<>(); - - vepMeta.put("Gene", org.molgenis.vcf.utils.model.NestedField.builder().index(4).numberCount(1) - .numberType(NumberType.NUMBER) - .type(org.molgenis.vcf.utils.model.ValueType.STRING).label("Gene").description("Gene") - .build()); - vepMeta.put("SYMBOL_SOURCE", org.molgenis.vcf.utils.model.NestedField.builder().index(21).numberCount(1) - .numberType(NumberType.NUMBER) - .type(org.molgenis.vcf.utils.model.ValueType.STRING).label("Gene").description("Gene") - .build()); - vepMeta.put("InheritanceModesGene", org.molgenis.vcf.utils.model.NestedField.builder().index(24).numberCount(1) - .numberType(NumberType.NUMBER) - .type(org.molgenis.vcf.utils.model.ValueType.STRING).label("Gene").description("Gene") - .build()); - vepMeta.put("IncompletePenetrance", org.molgenis.vcf.utils.model.NestedField.builder().index(-1).numberCount(1) - .numberType(NumberType.NUMBER) - .type(org.molgenis.vcf.utils.model.ValueType.STRING).label("Gene").description("Gene") - .build()); - when(fieldMetadataService.load(infoHeader)).thenReturn( - FieldMetadata.builder().nestedFields(vepMeta).build()); - when(header.getInfoHeaderLines()).thenReturn(Collections.singletonList(infoHeader)); - vepMetadata = new VepMetadata(header, fieldMetadataService); - } - - @Test - void getGenes() { - when(vc.getAttributeAsStringList("CSQ", "")).thenReturn(Arrays.asList( - "G|missense_variant|MODERATE|TEST1|ENSG00000123456|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>G|ENSP00000366410.1:p.Arg207Gly|763|619|207|R/G|Cgg/Ggg|||1||HGNC|17877||AD&AR|Leber_congenital_amaurosis_9:AR|", - "T|missense_variant|MODERATE|TEST2|ENSG00000123457|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XL&ICI|Leber_congenital_amaurosis_9:AR|", - "T|missense_variant|MODERATE|TEST2|ENSG00000123458|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XLR&XLD|Leber_congenital_amaurosis_9:AR|")); - - VcfRecordGenes expected = VcfRecordGenes.builder() - .genes(Map.of("ENSG00000123457", new Gene("ENSG00000123457","HGNC", Set.of(XLD, XLR)), "ENSG00000123456", - new Gene("ENSG00000123456","HGNC", Set.of(AD, AR)), "ENSG00000123458", - new Gene("ENSG00000123458","HGNC", Set.of(XLD, XLR)))).build(); - VcfRecord vcfRecord = new VcfRecord(vc, vepMetadata, emptySet()); - assertEquals(expected, vcfRecord.getVcfRecordGenes()); - } - - @Test - void getGenesEmptyValues() { - VariantContext vc2 = mock(VariantContext.class, "vc2"); - when(vc2.getAttributeAsStringList("CSQ", "")).thenReturn(Arrays.asList( - "G|missense_variant|MODERATE|TEST1|ENSG00000123456|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>G|ENSP00000366410.1:p.Arg207Gly|763|619|207|R/G|Cgg/Ggg|||1||HGNC|17877||AD&AR|Leber_congenital_amaurosis_9:AR|", - "T|missense_variant|MODERATE||ENSG00000123457|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XL&ICI|Leber_congenital_amaurosis_9:AR|", - "T|missense_variant|MODERATE|||Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>T|ENSP00000366410.1:p.Arg207Trp|763|619|207|R/W|Cgg/Tgg|||1||HGNC|17877||XLR&XLD|Leber_congenital_amaurosis_9:AR|")); - - VcfRecordGenes expected = VcfRecordGenes.builder().containsVcWithoutGene(true).genes(Map - .of("ENSG00000123457", new Gene("ENSG00000123457", "HGNC", Set.of(XLD, XLR)), "ENSG00000123456", - new Gene("ENSG00000123456", "HGNC", Set.of(AD, AR)))).build(); - VcfRecord vcfRecord = new VcfRecord(vc2, vepMetadata, emptySet()); - assertEquals(expected, vcfRecord.getVcfRecordGenes()); - } - - @Test - void getGenesEmptySymbolSource() { - VariantContext variantContext = mock(VariantContext.class); - when(variantContext.getAttributeAsStringList(eq("CSQ"), any())).thenReturn(List.of( - "G|missense_variant|MODERATE|TEST1|ENSG00000123456|Transcript|ENST00000377205|protein_coding|5/5||ENST00000377205.1:c.619C>G|ENSP00000366410.1:p.Arg207Gly|763|619|207|R/G|Cgg/Ggg|||1|||17877||AD&AR|Leber_congenital_amaurosis_9:AR|")); - VcfRecord vcfRecord = new VcfRecord(variantContext, vepMetadata, emptySet()); - assertEquals(VcfRecordGenes.builder().genes(Map.of()).containsVcWithoutGene(true).build(), vcfRecord.getVcfRecordGenes()); - } -} \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java index 327b932..fa8b5b0 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java @@ -1,27 +1,23 @@ package org.molgenis.vcf.inheritance.matcher.checker; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.createGenotype; import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; + import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -35,16 +31,16 @@ class AdCheckerTest { final AdChecker adChecker = new AdChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adChecker.check(vcfRecord, family)); + assertEquals(expected, adChecker.check(variantGeneRecord, family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:ADtests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -75,8 +71,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),""), family, expected, testName); + .createVariantContext(genotypes,""), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java index 9a089c6..0d32a4e 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java @@ -1,7 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptySet; +import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.FALSE; @@ -15,7 +14,6 @@ import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -23,10 +21,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -38,28 +35,25 @@ class AdNonPenCheckerTest { private final AdNonPenetranceChecker adNonPenetranceChecker = new AdNonPenetranceChecker(); - @Mock - VepMetadata vepMetadata; - @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adNonPenetranceChecker.check(vcfRecord, family, FALSE)); + assertEquals(expected, adNonPenetranceChecker.check(variantGeneRecord, family)); } @Test void testCheckAd() { VariantContext variantContext = mock(VariantContext.class); Pedigree family = mock(Pedigree.class); - assertEquals(FALSE, adNonPenetranceChecker.check(new VcfRecord(variantContext, vepMetadata, emptySet()), family, MatchEnum.TRUE)); + assertEquals(FALSE, adNonPenetranceChecker.check(new VariantGeneRecord(variantContext, emptySet(), new GeneInfo("TEST", "SOURCE", emptySet())), family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:ADNonPenTests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -90,8 +84,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),""), family, expected, testName); + .createVariantContext(genotypes,""), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java index 27403c7..1672a14 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java @@ -5,21 +5,19 @@ import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; + import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -33,16 +31,16 @@ class ArCheckerTest { final ArChecker arChecker = new ArChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, arChecker.check(vcfRecord, family)); + assertEquals(expected, arChecker.check(variantGeneRecord, family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:ARTests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -73,8 +71,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),""), family, expected, testName); + .createVariantContext(genotypes,""), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java index f65b813..f47d5a7 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java @@ -1,10 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Collections.singletonMap; +import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.Mockito.when; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.FALSE; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.TRUE; import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.createGenotype; @@ -18,16 +15,15 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; +import java.util.Set; import java.util.stream.Stream; + import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -38,89 +34,84 @@ @ExtendWith(MockitoExtension.class) class ArCompoundCheckerTest { - @Mock - private VepMetadata vepMetadata; - private final static Gene gene1 = new Gene("GENE1", "EntrezGene", singleton(InheritanceMode.AR)); - - @ParameterizedTest(name = "{index} {4}") - @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Map> geneVariantMap, - Pedigree family, String expectedString, - String displayName) { - MatchEnum expected = mapExpectedString(expectedString); - ArCompoundChecker arCompoundChecker = new ArCompoundChecker(vepMetadata); - List compounds = arCompoundChecker.check(geneVariantMap, vcfRecord, family, FALSE); - if(expected == FALSE) { - assertTrue(compounds.isEmpty()); - }else if(expected == TRUE){ - assertTrue(compounds.stream().anyMatch(CompoundCheckResult::isCertain)); - }else{ - assertTrue(!compounds.isEmpty() && compounds.stream().noneMatch(CompoundCheckResult::isCertain)); + @ParameterizedTest(name = "{index} {4}") + @MethodSource("provideTestCases") + void check(VariantGeneRecord variantGeneRecord, Map> geneVariantMap, + Pedigree family, String expectedString, + String displayName) { + MatchEnum expected = mapExpectedString(expectedString); + ArCompoundChecker arCompoundChecker = new ArCompoundChecker(); + Set compounds = arCompoundChecker.check(geneVariantMap, variantGeneRecord, family); + if (expected == FALSE) { + assertTrue(compounds.isEmpty()); + } else if (expected == TRUE) { + assertTrue(compounds.stream().anyMatch(CompoundCheckResult::isCertain)); + } else { + assertTrue(!compounds.isEmpty() && compounds.stream().noneMatch(CompoundCheckResult::isCertain)); + } } - } - private static Stream provideTestCases() throws IOException { - File testFile = ResourceUtils.getFile("classpath:ArCompoundTests.tsv"); - List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + private static Stream provideTestCases() throws IOException { + File testFile = ResourceUtils.getFile("classpath:ArCompoundTests.tsv"); + List lines = Files.lines(testFile.toPath()) + .map(line -> line.split("\t")).toList(); - return lines.stream().skip(1).map(line -> { - String testName = line[0]; - String probandGt = line[1]; - String probandOtherGt = line[2]; - AffectedStatus probandAffectedStatus = AffectedStatus.valueOf(line[3]); - Sex probandSex = Sex.valueOf(line[4]); - String fatherGt = line[5]; - String fatherOtherGt = line[6]; - AffectedStatus fatherAffectedStatus = null; - if (!line[7].isEmpty()) { - fatherAffectedStatus = AffectedStatus.valueOf(line[7]); - } - String motherGt = line[8]; - String motherOtherGt = line[9]; - AffectedStatus motherAffectedStatus = null; - if (!line[10].isEmpty()) { - motherAffectedStatus = AffectedStatus.valueOf(line[10]); - } - String brotherGt = line[11]; - String brotherOtherGt = line[12]; - AffectedStatus brotherAffectedStatus = - line[13].isEmpty() ? null : AffectedStatus.valueOf(line[13]); - String expected = line[14]; + return lines.stream().skip(1).map(line -> { + String testName = line[0]; + String probandGt = line[1]; + String probandOtherGt = line[2]; + AffectedStatus probandAffectedStatus = AffectedStatus.valueOf(line[3]); + Sex probandSex = Sex.valueOf(line[4]); + String fatherGt = line[5]; + String fatherOtherGt = line[6]; + AffectedStatus fatherAffectedStatus = null; + if (!line[7].isEmpty()) { + fatherAffectedStatus = AffectedStatus.valueOf(line[7]); + } + String motherGt = line[8]; + String motherOtherGt = line[9]; + AffectedStatus motherAffectedStatus = null; + if (!line[10].isEmpty()) { + motherAffectedStatus = AffectedStatus.valueOf(line[10]); + } + String brotherGt = line[11]; + String brotherOtherGt = line[12]; + AffectedStatus brotherAffectedStatus = + line[13].isEmpty() ? null : AffectedStatus.valueOf(line[13]); + String expected = line[14]; - Pedigree family = PedigreeTestUtil - .createFamily(probandSex, probandAffectedStatus, fatherAffectedStatus, - motherAffectedStatus, brotherAffectedStatus, "FAM001"); - List genotypes = new ArrayList<>(); - genotypes.add(createGenotype("Patient", probandGt)); - if (!fatherGt.isEmpty()) { - genotypes.add(createGenotype("Father", fatherGt)); - } - if (!motherGt.isEmpty()) { - genotypes.add(createGenotype("Mother", motherGt)); - } - if (!brotherGt.isEmpty()) { - genotypes.add(createGenotype("Brother", brotherGt)); - } + Pedigree family = PedigreeTestUtil + .createFamily(probandSex, probandAffectedStatus, fatherAffectedStatus, + motherAffectedStatus, brotherAffectedStatus, "FAM001"); + List genotypes = new ArrayList<>(); + genotypes.add(createGenotype("Patient", probandGt)); + if (!fatherGt.isEmpty()) { + genotypes.add(createGenotype("Father", fatherGt)); + } + if (!motherGt.isEmpty()) { + genotypes.add(createGenotype("Mother", motherGt)); + } + if (!brotherGt.isEmpty()) { + genotypes.add(createGenotype("Brother", brotherGt)); + } - List otherGenotypes = new ArrayList<>(); - otherGenotypes.add(createGenotype("Patient", probandOtherGt)); - if (!fatherGt.isEmpty()) { - otherGenotypes.add(createGenotype("Father", fatherOtherGt)); - } - if (!motherGt.isEmpty()) { - otherGenotypes.add(createGenotype("Mother", motherOtherGt)); - } - if (!brotherGt.isEmpty()) { - otherGenotypes.add(createGenotype("Brother", brotherOtherGt)); - } + List otherGenotypes = new ArrayList<>(); + otherGenotypes.add(createGenotype("Patient", probandOtherGt)); + if (!fatherGt.isEmpty()) { + otherGenotypes.add(createGenotype("Father", fatherOtherGt)); + } + if (!motherGt.isEmpty()) { + otherGenotypes.add(createGenotype("Mother", motherOtherGt)); + } + if (!brotherGt.isEmpty()) { + otherGenotypes.add(createGenotype("Brother", brotherOtherGt)); + } - return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",0,1,-1,-1,-1),"GENE1|Entrez"), - singletonMap("GENE1", singletonList(VariantContextTestUtil - .createVariantContext(otherGenotypes, - new VepMetadata("CSQ",0,1,-1,-1,-1),"GENE1|Entrez"))), family, expected, testName); - }); - } + return Arguments.of(VariantContextTestUtil.createVariantContext(genotypes, "GENE1|Entrez|1|P,GENE1|Entrez|2|V,GENE1|Entrez|3|B"), + singletonMap(new GeneInfo("GENE1", "SOURCE", emptySet()), + singletonList( + VariantContextTestUtil.createVariantContext(otherGenotypes, "GENE1|Entrez|1|P,GENE1|Entrez|2|V,GENE1|Entrez|3|B,GENE1|Entrez|4|V"))), + family, expected, testName); + }); + } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java index 847f081..b3b6578 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java @@ -4,19 +4,19 @@ import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.createGenotype; import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; -import htsjdk.variant.variantcontext.VariantContext; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; +import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.model.InheritanceResult; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -30,17 +30,17 @@ class DeNovoCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); Sample individual = family.getMembers().get("Patient"); - assertEquals(expected, deNovoChecker.checkDeNovo(vcfRecord, individual)); + assertEquals(expected, deNovoChecker.checkDeNovo(variantRecord, individual)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:DenovoTests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -54,11 +54,12 @@ private static Stream provideTestCases() throws IOException { Pedigree family = PedigreeTestUtil .createFamily(probandSex, AffectedStatus.MISSING, AffectedStatus.MISSING, AffectedStatus.MISSING, "FAM001"); - return Arguments.of(VariantContextTestUtil - .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), - createGenotype("Father", fatherGt), - createGenotype("Mother", motherGt)), - new VepMetadata("CSQ",-1,-1,-1,-1,-1), "", chrom), family, expected, testName); + VariantGeneRecord record = VariantContextTestUtil + .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), + createGenotype("Father", fatherGt), + createGenotype("Mother", motherGt)), "", chrom); + + return Arguments.of(new VariantRecord(Map.of(record.getGeneInfo(), record), record.unwrap(),InheritanceResult.builder().build()), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java index 282bbd2..b0699b4 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java @@ -1,14 +1,12 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -21,7 +19,6 @@ import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -35,16 +32,16 @@ class MtCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, mtChecker.check(vcfRecord, family)); + assertEquals(expected, mtChecker.check(variantGeneRecord, family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:MTtests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -75,8 +72,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),"", "chrM"), family, expected, testName); + .createVariantContext(genotypes,"", "chrM"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/PedigreeTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/PedigreeTestUtil.java index abd8add..93d7b82 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/PedigreeTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/PedigreeTestUtil.java @@ -34,23 +34,6 @@ public static Pedigree createFamily(Sex probandSex, return Pedigree.builder().id(familyId).members(result).build(); } - public static Pedigree createExtendedFamily() { - Map result = new HashMap<>(); - result.put("Patient", createSample(Sex.MALE, AffectedStatus.AFFECTED, "TEST", "Patient", "Father", - "Mother")); - result.put("Mother",createSample(Sex.FEMALE, AffectedStatus.UNAFFECTED, "TEST", "Mother", "", "")); - result.put("Father",createSample(Sex.MALE, AffectedStatus.UNAFFECTED, "TEST", "Father", "Grandfather", "Grandmother")); - result.put("Brother",createSample(Sex.MALE, AffectedStatus.AFFECTED, "TEST", "Brother", "Father", "Mother")); - result.put("Grandmother",createSample(Sex.FEMALE, AffectedStatus.UNAFFECTED, "TEST", "Grandmother", "GreatGrandfather", "GreatGrandmother")); - result.put("Grandfather",createSample(Sex.MALE, AffectedStatus.UNAFFECTED, "TEST", "Grandfather", "", "")); - result.put("GreatGrandfather",createSample(Sex.FEMALE, AffectedStatus.UNAFFECTED, "TEST", "GreatGrandfather", "", "")); - result.put("GreatGrandmother",createSample(Sex.MALE, AffectedStatus.UNAFFECTED, "TEST", "GreatGrandmother", "", "")); - result.put("Uncle",createSample(Sex.MALE, AffectedStatus.AFFECTED, "TEST", "Uncle", "Grandfather", "Grandmother")); - result.put("HalfUncle",createSample(Sex.MALE, AffectedStatus.AFFECTED, "TEST", "Uncle", "Grandfather", "OtherMother")); - result.put("UncleInLaw",createSample(Sex.MALE, AffectedStatus.AFFECTED, "TEST", "Uncle", "OtherFather", "OtherMother")); - return Pedigree.builder().id("TEST").members(result).build(); - } - public static Sample createSample(Sex sex, AffectedStatus affectedStatus, String familyId, String patient, String father, String mother) { Person person = Person.builder().individualId(patient).familyId(familyId).paternalId(father) .maternalId(mother).sex(sex).affectedStatus(affectedStatus) diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java index 1532bf6..d46e567 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java @@ -5,19 +5,17 @@ import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; + import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,16 +29,16 @@ class XldCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xldChecker.check(vcfRecord, family)); + assertEquals(expected, xldChecker.check(variantGeneRecord, family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:XldTests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -71,8 +69,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),"", "chrX"), family, expected, testName); + .createVariantContext(genotypes, "", "chrX"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java index 144b5e4..8572e7d 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java @@ -5,19 +5,17 @@ import static org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil.mapExpectedString; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; + import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,16 +29,16 @@ class XlrCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xlrChecker.check(vcfRecord, family)); + assertEquals(expected, xlrChecker.check(variantGeneRecord, family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:XlrTests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -71,8 +69,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),"", "X"), family, expected, testName); + .createVariantContext(genotypes, "","X"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java index 67ab698..a8abf4f 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java @@ -1,14 +1,12 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Genotype; -import htsjdk.variant.variantcontext.VariantContext; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -21,7 +19,6 @@ import java.nio.file.Files; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -35,16 +32,16 @@ class YlCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VcfRecord vcfRecord, Pedigree family, String expectedString, + void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, ylChecker.check(vcfRecord, family)); + assertEquals(expected, ylChecker.check(variantGeneRecord, family)); } private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:YLtests.tsv"); List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).collect(Collectors.toList()); + .map(line -> line.split("\t")).toList(); return lines.stream().skip(1).map(line -> { String testName = line[0]; @@ -75,8 +72,7 @@ private static Stream provideTestCases() throws IOException { genotypes.add(createGenotype("Brother", brotherGt)); } return Arguments.of(VariantContextTestUtil - .createVariantContext(genotypes, - new VepMetadata("CSQ",-1,-1,-1,-1,-1),"","chrY"), family, expected, testName); + .createVariantContext(genotypes, "", "chrY"), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceResultServiceFactoryImplTest.java similarity index 85% rename from src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java rename to src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceResultServiceFactoryImplTest.java index d0a49ba..a9185dd 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceServiceFactoryImplTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceResultServiceFactoryImplTest.java @@ -11,12 +11,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; @ExtendWith(MockitoExtension.class) -class InheritanceServiceFactoryImplTest { +class InheritanceResultServiceFactoryImplTest { @Mock private Annotator annotator; @Mock - private VepMetadata vepMetadata; - @Mock private PedigreeInheritanceChecker pedigreeInheritanceChecker; private InheritanceServiceFactoryImpl inheritanceServiceFactoryImpl; @@ -26,7 +24,7 @@ void setUp() { } @Test void create() { - InheritanceService inheritanceServiceFactory = inheritanceServiceFactoryImpl.create(Settings.builder().build(), vepMetadata); + InheritanceService inheritanceServiceFactory = inheritanceServiceFactoryImpl.create(Settings.builder().build()); assertNotNull(inheritanceServiceFactory); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java index 9eb5239..a912f9d 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java @@ -4,79 +4,89 @@ import htsjdk.variant.variantcontext.Genotype; import htsjdk.variant.variantcontext.GenotypeBuilder; import htsjdk.variant.variantcontext.VariantContextBuilder; -import org.molgenis.vcf.inheritance.matcher.VcfRecord; -import org.molgenis.vcf.inheritance.matcher.VepMetadata; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.*; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptySet; +import static htsjdk.variant.variantcontext.Allele.*; +import static java.util.Collections.*; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; public class VariantContextTestUtil { - public static final Allele REF = Allele.REF_T; - public static final Allele ALT = Allele.ALT_A; + public static final Allele REF = Allele.REF_T; - public static VcfRecord createVariantContext(List genotypes, VepMetadata vepMetadata, String VepData) { - return createVariantContext(genotypes, vepMetadata, VepData, "1"); - } + public static VariantGeneRecord createVariantContext(List genotypes, String VepData) { + return createVariantContext(genotypes, VepData, "1"); + } - public static VcfRecord createVariantContext(List genotypes, VepMetadata vepMetadata, String VepData, - String contig) { - VariantContextBuilder builder = new VariantContextBuilder(); - builder.chr(contig); - builder.start(12345); - builder.stop(12345); - builder.alleles(Arrays.asList(REF, ALT)); - builder.genotypes(genotypes); - builder.attribute("CSQ", VepData); - return new VcfRecord(builder.make(), vepMetadata, emptySet()); - } + public static VariantGeneRecord createVariantContext(List genotypes, String VepData, String contig) { + VariantContextBuilder builder = new VariantContextBuilder(); + builder.chr(contig); + builder.start(12345); + builder.stop(12345); + builder.alleles(Arrays.asList(REF, ALT_A, Allele.ALT_G, Allele.ALT_C, Allele.ALT_N)); + builder.genotypes(genotypes); + builder.attribute("CSQ", VepData); - public static Genotype createGenotype(String sample, String gt) { - boolean isPhased = false; - String[] gtSplit; - if (gt.contains("|")) { - isPhased = true; - gtSplit = gt.split("\\|"); - } else if (gt.contains("/")) { - gtSplit = gt.split("/"); - } else { - gtSplit = new String[]{gt}; + return new VariantGeneRecord(builder.make(), Set.of(ALT_A,ALT_G,ALT_N), new GeneInfo("GENE1", "SOURCE", emptySet())); } - List alleles = new ArrayList<>(); - alleles.add(getAllele(gtSplit, 0)); - if (gtSplit.length > 1) { - alleles.add(getAllele(gtSplit, 1)); + + public static Genotype createGenotype(String sample, String gt) { + boolean isPhased = false; + String[] gtSplit; + if (gt.contains("|")) { + isPhased = true; + gtSplit = gt.split("\\|"); + } else if (gt.contains("/")) { + gtSplit = gt.split("/"); + } else { + gtSplit = new String[]{gt}; + } + List alleles = new ArrayList<>(); + alleles.add(getAllele(gtSplit, 0)); + if (gtSplit.length > 1) { + alleles.add(getAllele(gtSplit, 1)); + } + GenotypeBuilder genotypeBuilder = new GenotypeBuilder(); + genotypeBuilder.name(sample); + genotypeBuilder.alleles(alleles); + genotypeBuilder.phased(isPhased); + return genotypeBuilder.make(); } - GenotypeBuilder genotypeBuilder = new GenotypeBuilder(); - genotypeBuilder.name(sample); - genotypeBuilder.alleles(alleles); - genotypeBuilder.phased(isPhased); - return genotypeBuilder.make(); - } - private static Allele getAllele(String[] gtSplit, int i) { - if (gtSplit[i].equals("0")) { - return REF; - } else if (gtSplit[i].equals(".")) { - return Allele.NO_CALL; - } else { - return ALT; + private static Allele getAllele(String[] gtSplit, int i) { + switch (gtSplit[i]) { + case "0" -> { + return REF; + } + case "1" -> { + return ALT_A; + } + case "2" -> { + return ALT_G; + } + case "3" -> { + return ALT_C; + } + case "4" -> { + return ALT_N; + } + default -> { + return NO_CALL; + } + } } - } - public static MatchEnum mapExpectedString(String expectedString) { - return switch (expectedString) { - case "true" -> TRUE; - case "false" -> FALSE; - case "possible" -> POTENTIAL; - default -> throw new IllegalArgumentException("Value should be true, false or possible."); - }; - } + public static MatchEnum mapExpectedString(String expectedString) { + return switch (expectedString) { + case "true" -> TRUE; + case "false" -> FALSE; + case "possible" -> POTENTIAL; + default -> throw new IllegalArgumentException("Value should be true, false or possible."); + }; + } } \ No newline at end of file diff --git a/src/test/resources/ADtests.tsv b/src/test/resources/ADtests.tsv index b632b8a..869eeb3 100644 --- a/src/test/resources/ADtests.tsv +++ b/src/test/resources/ADtests.tsv @@ -30,4 +30,7 @@ MixedParents2 0/1 AFFECTED MALE ./0 UNAFFECTED 0/0 UNAFFECTED 0/0 UNAFFECTED pos MixedParents3 0/1 AFFECTED MALE ./0 UNAFFECTED ./0 UNAFFECTED 0/0 UNAFFECTED possible MixedParents4 0/1 AFFECTED MALE ./. UNAFFECTED 0/1 UNAFFECTED 0/0 UNAFFECTED false MixedParents5 0/1 AFFECTED MALE ./1 UNAFFECTED 0/0 UNAFFECTED 0/0 UNAFFECTED false -MixedParents6 0/1 AFFECTED MALE ./0 UNAFFECTED 0/1 UNAFFECTED 0/0 UNAFFECTED false \ No newline at end of file +MixedParents6 0/1 AFFECTED MALE ./0 UNAFFECTED 0/1 UNAFFECTED 0/0 UNAFFECTED false +multiallelic_denovo 0/2 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED true +multiallelic_denovo_fatherHas1 1/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED possible +multiallelic_father_has_it 0/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED false \ No newline at end of file diff --git a/src/test/resources/ArCompoundTests.tsv b/src/test/resources/ArCompoundTests.tsv index d146967..99107d8 100644 --- a/src/test/resources/ArCompoundTests.tsv +++ b/src/test/resources/ArCompoundTests.tsv @@ -11,7 +11,7 @@ BrotherAffectedHasOne 1/0 0/1 AFFECTED MALE 0/1 0/0 UNAFFECTED 0/1 0/0 UNAFFECTE BrotherAffectedHasBoth 1/0 0/1 AFFECTED MALE 0/1 0/0 UNAFFECTED 0/1 0/0 UNAFFECTED 0/1 0/1 AFFECTED true mixed1 1/0 0/1 AFFECTED MALE 0/1 0/0 UNAFFECTED ./1 0/0 UNAFFECTED 0/0 0/1 UNAFFECTED true mixed2 1/0 0/. AFFECTED MALE 0/0 0/1 UNAFFECTED 0/1 0/. UNAFFECTED 0/1 0/. UNAFFECTED possible -mixed3 ./0 0/. AFFECTED MALE 0/1 0/0 UNAFFECTED 0/1 ./0 UNAFFECTED 0/1 0/1 UNAFFECTED false +mixed3 ./0 0/. AFFECTED MALE 0/1 0/0 UNAFFECTED 0/1 ./0 UNAFFECTED 0/1 0/1 UNAFFECTED possible missing1 1/0 0/1 AFFECTED MALE 0/0 ./. UNAFFECTED ./. 0/0 UNAFFECTED 0/0 0/0 UNAFFECTED true missing2 1/0 0/1 AFFECTED MALE 1/0 ./. UNAFFECTED ./. 1/0 UNAFFECTED 0/0 0/0 UNAFFECTED possible missing3 1/0 0/1 AFFECTED MALE 1/0 ./. UNAFFECTED ./. 0/0 UNAFFECTED 0/0 0/0 UNAFFECTED possible @@ -20,4 +20,8 @@ missing5 1/1 ./. AFFECTED MALE 1/0 ./. UNAFFECTED ./. 0/0 UNAFFECTED 0/0 0/0 UNA missing6 ./. ./. AFFECTED MALE 1/0 ./. UNAFFECTED ./. 0/0 UNAFFECTED 0/0 0/0 UNAFFECTED possible Unknown1 1/0 0/1 AFFECTED MALE 0/1 0/1 MISSING 0/1 0/0 UNAFFECTED 0/0 0/1 UNAFFECTED possible Unknown2 1/0 0/1 AFFECTED MALE 0/0 0/1 MISSING 0/0 0/1 UNAFFECTED 0/1 0/. UNAFFECTED possible -Unknown3 1/0 0/1 AFFECTED MALE 0/1 0/0 MISSING 0/1 1/0 UNAFFECTED 0/1 0/1 UNAFFECTED false \ No newline at end of file +Unknown3 1/0 0/1 AFFECTED MALE 0/1 0/0 MISSING 0/1 1/0 UNAFFECTED 0/1 0/1 UNAFFECTED false +multiallelic1 1/2 0/1 AFFECTED MALE 0/1 0/0 UNAFFECTED 0/0 1/0 UNAFFECTED 0/0 0/0 UNAFFECTED possible +multiallelic2 2/2 0/1 AFFECTED MALE 0/1 0/0 UNAFFECTED 0/0 1/0 UNAFFECTED 0/0 0/0 UNAFFECTED false +multiallelic3 2/4 0/1 AFFECTED MALE 0/1 0/0 UNAFFECTED 0/0 1/0 UNAFFECTED 0/0 0/0 UNAFFECTED possible +multiallelic4 2/4 0/1 AFFECTED MALE 4/4 0/1 AFFECTED 0/0 1/0 UNAFFECTED 0/0 0/0 UNAFFECTED false \ No newline at end of file diff --git a/src/test/resources/XldTests.tsv b/src/test/resources/XldTests.tsv index d8615de..f3ac7eb 100644 --- a/src/test/resources/XldTests.tsv +++ b/src/test/resources/XldTests.tsv @@ -20,7 +20,7 @@ mixed2 1 AFFECTED MALE 0 UNAFFECTED ./0 UNAFFECTED 0 UNAFFECTED true mixed3 1 AFFECTED MALE 0 UNAFFECTED ./0 UNAFFECTED 1 AFFECTED true mixed4 1 AFFECTED MALE 0 UNAFFECTED ./0 UNAFFECTED 0 AFFECTED false mixed5 1/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 1 UNAFFECTED false -mixed5 1/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED true -mixed6 0/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED possible +mixed6 1/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED true +mixed7 0/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED possible Unknown1 1 AFFECTED MALE 0 MISSING 0/0 UNAFFECTED possible Unknown2 1 AFFECTED MALE 1 MISSING 0/0 UNAFFECTED possible \ No newline at end of file diff --git a/src/test/resources/YLtests.tsv b/src/test/resources/YLtests.tsv index 79d2cd0..1ad2260 100644 --- a/src/test/resources/YLtests.tsv +++ b/src/test/resources/YLtests.tsv @@ -1,4 +1,3 @@ -name probandGt probandAffectedStatus probandSex fatherGt fatherAffectedStatus motherGt motherAffectedStatus brotherGt brotherAffectedStatus expected denovoHet 0/1 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED possible denovoHom 1/1 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED true denovoHomRef 0/0 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED false @@ -32,6 +31,11 @@ HomRef4 0/0 AFFECTED MALE 1/. AFFECTED 0/0 UNAFFECTED false Hap 1 AFFECTED MALE 0 UNAFFECTED 0 UNAFFECTED true Hap2 1 AFFECTED MALE . UNAFFECTED 0 UNAFFECTED possible Hap3 1 AFFECTED MALE 0 UNAFFECTED 1 UNAFFECTED true -Hap4 1 AFFECTED MALE 0 UNAFFECTED 1 AFFECTED true +Hap4 1 AFFECTED MALE 0 UNAFFECTED 1 AFFECTED false HapMiss . AFFECTED MALE 0 UNAFFECTED 0 UNAFFECTED possible -HapRef 0 AFFECTED MALE 0 UNAFFECTED 0 UNAFFECTED false \ No newline at end of file +HapRef 0 AFFECTED MALE 0 UNAFFECTED 0 UNAFFECTED false +HapMulti 1 AFFECTED MALE 2 UNAFFECTED 0 UNAFFECTED possible +HapMulti2 1 AFFECTED MALE 2 UNAFFECTED 0 UNAFFECTED 1 UNAFFECTED false +multiallelic_denovo 0/2 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED possible +multiallelic_denovo_fatherHas1 1/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED possible +multiallelic_father_has_it 0/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED possible \ No newline at end of file diff --git a/src/test/resources/expected_noParents.vcf b/src/test/resources/expected_noParents.vcf index 2b417cb..468810c 100644 --- a/src/test/resources/expected_noParents.vcf +++ b/src/test/resources/expected_noParents.vcf @@ -3,11 +3,11 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= -##INFO= +##FORMAT= +##INFO= ##INFO= ##INFO= ##INFO= @@ -41,17 +41,17 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:.:ID2:1 0/0:50 0/0:50 1/0:50:AD_IP,AR_C:1_123459_C_G:.:ID1,ID2:1 0/0:50 1/0:50 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:1_123460_C_G:.:ID3 ./.:50 0/0:50 1/0:50:AD,AR_C:1_123460_C_G,1_123459_C_G:.:ID3:1 1/0:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP:.:.:.:0 1/1:50 0/1:50 1/0:50:AD,AR_C:1_123458_C_G,1_123460_C_G:.:ID3:1 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:.:.:ID1,ID2:1 0/1:50 0/1:50 1/0:50:AD,AR_C:1_123457_C_G:.:ID1,ID2:1 1/0:50 0/0:50 -1 123460 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP,AR_C:1_123458_C_G:.:ID3:1 1/0:50 0/0:50 1/0:50:AD,AR_C:1_123458_C_G,1_123459_C_G:.:ID3:1 1/0:50 0/0:50 -1 123461 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP:.:.:ID4:1 0/0:50 1/0:50 1/0:50:AD:.:.:ID4:1 1/0:50 0/0:50 -2 1 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIM 1/0:50:AD_IP 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 -3 2 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIM 1/0:50:AD_IP 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 -4 123457 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:.:ID8:1 0/0:50 0/0:50 1/0:50:AD,AR_C:4_123459_C_G,4_123458_C_G:.:ID8:1 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:.:.:ID8:1 1/0:50 0/0:50 1/0:50:AD,AR_C:4_123459_C_G,4_123457_C_G:.:ID8:1 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:.:.:ID8:1 0/0:50 0/0:50 1/0:50:AD,AR_C:4_123458_C_G,4_123457_C_G:.:ID8:1 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5||XLR,G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIM 1/0:50:XLD,XLR:.:.:0 0/0:50 0/0:50 1/0:50:.:.:.:0 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIM 1/0:50:XLD,XLR ./.:50 0/0:50 1/0:50:XLD,XLR 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIM 1/1:50:.:.:.:0 0/1:50 0/1:50 1/0:50:XLD,XLR:.:.:0 1/0:50 0/0:50 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,::ID2:0,1 0/0:50 0/0:50 1/0:50:AD_IP,AD_IP:,::ID2:0,1 0/0:50 1/0:50 +1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP,AR&AD_IP:,::ID1,ID2:1,1 0/1:50 0/1:50 1/0:50:AD,AD:,::ID2:0,1 1/0:50 0/0:50 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::::0 1/0:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP:::ID4:1 0/0:50 1/0:50 1/0:50:AD:::ID4:1 1/0:50 0/0:50 +2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 +3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 +4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP:::ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:::0,0 0/0:50 0/0:50 1/0:50:XLD,XLD:,:::0,0 0/0:50 1/0:50 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID6 ./.:50 0/0:50 1/0:50:XLD:::ID6 1/0:50 0/0:50 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index 63bb426..2a73a8a 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -3,11 +3,11 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= -##INFO= +##FORMAT= +##INFO= ##INFO= ##INFO= ##INFO= @@ -41,17 +41,17 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:.:ID2:1 0/0:50:.:.:.:.:0 0/0:50:.:.:.:.:0 1/0:50:AD,AR_C:1_123459_C_G:.:ID1,ID2:1 0/0:50:.:.:.:.:0 1/0:50:AD:.:.:ID2:1 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:1_123460_C_G:.:ID3:1 ./.:50:AR,AD,AR_C:1_123460_C_G:.:ID3 0/0:50:.:.:.:.:0 1/0:50:AD,AR_C:1_123460_C_G,1_123459_C_G:.:ID3:1 1/0:50:AD,AR_C:1_123460_C_G:.:ID3:1 0/0:50:.:.:.:.:0 -1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:.:.:ID3:1 1/1:50:AR,AD:.:.:ID3:1 0/1:50:AD:.:.:.:0 1/0:50:AD,AR_C:1_123458_C_G,1_123460_C_G:.:ID3:1 1/1:50:AR,AD:.:.:ID3:1 0/0:50:.:.:.:.:0 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:.:.:ID1,ID2:1 0/1:50:AD:.:.:ID2:1 0/1:50:AD:.:.:ID2:1 1/0:50:AD,AR_C:1_123457_C_G:.:ID1,ID2:1 1/0:50:AD:.:.:ID2:1 0/0:50:.:.:.:.:0 -1 123460 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:1_123458_C_G:.:ID3:1 1/0:50:AD,AR_C:1_123458_C_G:.:ID3:1 0/0:50:.:.:.:.:0 1/0:50:AD,AR_C:1_123458_C_G,1_123459_C_G:.:ID3:1 1/0:50:AD,AR_C:1_123458_C_G:.:ID3:1 0/0:50:.:.:.:.:0 -1 123461 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:.:ID4:1 0/0:50:.:.:.:.:0 1/0:50:AD:.:.:ID4:1 1/0:50:AD:.:.:ID4:1 1/0:50:AD:.:.:ID4:1 0/0:50:.:.:.:.:0 -2 1 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIM 1/0:50:AD 0/0:50:.:.:.:0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:.:.:.:0 -3 2 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIM 1/0:50:AD 0/0:50:.:.:.:0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:.:.:.:0 -4 123457 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:.:ID8:1 0/0:50:.:.:.:.:0 0/0:50:.:.:.:.:0 1/0:50:AD,AR_C:4_123459_C_G,4_123458_C_G:.:ID8:1 1/0:50:AD,AR_C:4_123459_C_G,4_123458_C_G:.:ID8:1 0/0:50:.:.:.:.:0 -4 123458 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:.:.:ID8:1 1/0:50:AD:.:.:ID8:1 0/0:50:.:.:.:.:0 1/0:50:AD,AR_C:4_123459_C_G,4_123457_C_G:.:ID8:1 1/0:50:AD,AR_C:4_123459_C_G,4_123457_C_G:.:ID8:1 0/0:50:.:.:.:.:0 -4 123459 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:.:.:ID8:1 0/0:50:.:.:.:.:0 0/0:50:.:.:.:.:0 1/0:50:AD,AR_C:4_123458_C_G,4_123457_C_G:.:ID8:1 1/0:50:AD,AR_C:4_123458_C_G,4_123457_C_G:.:ID8:1 0/0:50:.:.:.:.:0 -X 123457 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5||XLR,G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIM 1/0:50:XLD:.:.:0 0/0:50:.:.:.:0 0/0:50:.:.:.:0 1/0:50:XLD:.:.:0 0/0:50:.:.:.:0 1/0:50:XLD:.:.:0 -X 123458 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIM 1/0:50:XLD ./.:50:XLD,XLR 0/0:50:.:.:.:0 1/0:50:XLD 1/0:50:XLD 0/0:50:.:.:.:0 -X 123459 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIM 1/1:50:XLD,XLR:.:.:0 0/1:50:XLD:.:.:0 0/1:50:XLD:.:.:0 1/0:50:XLD:.:.:0 1/0:50:XLD:.:.:0 0/0:50:.:.:.:0 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,::ID2:0,1 0/0:50:,:,:::0,0 0/0:50:,:,:::0,0 1/0:50:AD,AD:,::ID2:0,1 0/0:50:,:,:::0,0 1/0:50:AD,AD:,::ID2:0,1 +1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50:AR_C:1_123460_C_G::ID3 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID3:1 1/1:50:AR&AD:::ID3:1 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR&AD:::ID3:1 0/0:50:::::0 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD,AR&AD:,::ID1,ID2:1,1 0/1:50:AD,AD:,::ID2:0,1 0/1:50:AD,AD:,::ID2:0,1 1/0:50:AD,AD:,::ID2:0,1 1/0:50:AD,AD:,::ID2:0,1 0/0:50:,:,:::0,0 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD&AR_C:1_123458_C_G::ID3:1 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 +1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID4:1 0/0:50:::::0 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 0/0:50:::::0 +2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 +3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 +4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:::0,0 0/0:50:,:,:::0,0 0/0:50:,:,:::0,0 1/0:50:XLD,XLD:,:::0,0 0/0:50:,:,:::0,0 1/0:50:XLD,XLD:,:::0,0 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID6 ./.:50:::::0 0/0:50:::::0 1/0:50:XLD:::ID6 1/0:50:XLD:::ID6 0/0:50:::::0 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50:::::0 diff --git a/src/test/resources/expected_noVEPinheritance.vcf b/src/test/resources/expected_noVEPinheritance.vcf index 60ea91c..445e14a 100644 --- a/src/test/resources/expected_noVEPinheritance.vcf +++ b/src/test/resources/expected_noVEPinheritance.vcf @@ -3,10 +3,10 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= +##FORMAT= ##INFO= ##INFO= ##INFO= @@ -39,10 +39,10 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIM 1/0:50:AD:.:1 0/0:50 0/0:50 1/0:50:AD_IP,AR_C:1_123459_C_G 0/0:50 1/0:50 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIM 1/0:50:AD ./.:50 0/0:50 1/0:50:AD,AR_C:1_123459_C_G 1/0:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIM 1/1:50:AD_IP:.:0 1/1:50 0/1:50 1/0:50:AD,AR_C:1_123458_C_G 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIM 1/1:50:AR,AD_IP:.:0 0/1:50 0/1:50 1/0:50:AD,AR_C:1_123457_C_G 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|,G|GENE6|EntrezGene|ID6| GT:DP:VI:VIC:VID:VIM 1/0:50:XLD,XLR:.:1 0/0:50 0/0:50 1/0:50:.:.:.:0 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIM 1/0:50:XLD,XLR ./.:50 0/0:50 1/0:50:XLD,XLR 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIM 1/1:50:.:.:0:0 0/1:50 0/1:50 1/0:50:XLD,XLR 1/0:50 0/0:50 +1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,:1:ID1,ID2 0/0:50:AD,AD:,::ID1,ID2 0/0:50:AD,AD:,::ID1,ID2 1/0:50:AD_IP,AD_IP:,::ID1,ID2 0/0:50 1/0:50:AD_IP,AD_IP:,::ID1,ID2 +1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID3 ./.:50:AD:::ID3 0/0:50:AD:::ID3 1/0:50:AD:::ID3 1/0:50 0/0:50:AD:::ID3 +1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0:ID3 1/1:50:AD_IP:::ID3 0/1:50:AD_IP:::ID3 1/0:50:AD:::ID3 1/1:50 0/0:50:AD:::ID3 +1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP,AR&AD_IP:,:0:ID1,ID2 0/1:50:AR&AD_IP,AR&AD_IP:,::ID1,ID2 0/1:50:AR&AD_IP,AR&AD_IP:,::ID1,ID2 1/0:50:AD,AD:,::ID1,ID2 1/0:50 0/0:50:AD,AD:,::ID1,ID2 +X 123457 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|,G|GENE6|EntrezGene|ID6| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:1:ID4,ID6 0/0:50:XLD,XLD:,::ID4,ID6 0/0:50:XLD,XLD:,::ID4,ID6 1/0:50:XLD,XLD:,::ID4,ID6 0/0:50 1/0:50:XLD,XLD:,::ID4,ID6 +X 123458 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID5 ./.:50:XLD:::ID5 0/0:50:XLD:::ID5 1/0:50:XLD:::ID5 1/0:50 0/0:50:XLD:::ID5 +X 123459 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::0:ID5 0/1:50:XLD&XLR:::ID5 0/1:50:XLD&XLR:::ID5 1/0:50:XLD:::ID5 1/0:50 0/0:50:XLD:::ID5 diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index 61c30e8..c07d138 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -3,11 +3,11 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= -##INFO= +##FORMAT= +##INFO= ##INFO= ##INFO= ##INFO= @@ -41,17 +41,17 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:1:ID2 0/0:50 0/0:50 1/0:50:AD_IP,AR_C:1_123459_C_G:.:ID1,ID2:1 0/0:50 1/0:50 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:1_123460_C_G:.:ID3 ./.:50 0/0:50 1/0:50:AD,AR_C:1_123460_C_G,1_123459_C_G:.:ID3:1 1/0:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP:.:0:.:0 1/1:50 0/1:50 1/0:50:AD,AR_C:1_123458_C_G,1_123460_C_G:.:ID3:1 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:.:0:ID1,ID2:1 0/1:50 0/1:50 1/0:50:AD,AR_C:1_123457_C_G:.:ID1,ID2:1 1/0:50 0/0:50 -1 123460 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP,AR_C:1_123458_C_G:0:ID3:1 1/0:50 0/0:50 1/0:50:AD,AR_C:1_123458_C_G,1_123459_C_G:.:ID3:1 1/0:50 0/0:50 -1 123461 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP:.:0:ID4:1 0/0:50 1/0:50 1/0:50:AD:.:.:ID4:1 1/0:50 0/0:50 -2 1 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIM 1/0:50:AD_IP:.:0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 -3 2 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIM 1/0:50:AD_IP:.:0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 -4 123457 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:.:1:ID8 0/0:50 0/0:50 1/0:50:AD,AR_C:4_123459_C_G,4_123458_C_G:.:ID8:1 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:.:1:ID8:1 1/0:50 0/0:50 1/0:50:AD,AR_C:4_123459_C_G,4_123457_C_G:.:ID8:1 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:.:1:ID8 0/0:50 0/0:50 1/0:50:AD,AR_C:4_123458_C_G,4_123457_C_G:.:ID8:1 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5||XLR,G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIM 1/0:50:XLD,XLR:.:1:0 0/0:50 0/0:50 1/0:50:.:.:.:0 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIM 1/0:50:XLD,XLR ./.:50 0/0:50 1/0:50:XLD,XLR 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIM 1/1:50:.:.:0:0 0/1:50 0/1:50 1/0:50:XLD,XLR:.:.:0 1/0:50 0/0:50 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,:1:ID2:0, 0/0:50 0/0:50 1/0:50:AD_IP,AD_IP:,::ID2:0,1 0/0:50 1/0:50 +1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP,AR&AD_IP:,:0:ID1,ID2:1,1 0/1:50 0/1:50 1/0:50:AD,AD:,::ID2:0,1 1/0:50 0/0:50 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0::0 1/0:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0:ID4:1 0/0:50 1/0:50 1/0:50:AD:::ID4:1 1/0:50 0/0:50 +2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 +3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 +4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP::1:ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:1::0,0 0/0:50 0/0:50 1/0:50:XLD,XLD:,:::0,0 0/0:50 1/0:50 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID6 ./.:50 0/0:50 1/0:50:XLD:::ID6 1/0:50 0/0:50 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 diff --git a/src/test/resources/integration.vcf b/src/test/resources/integration.vcf index ea52846..0d87c6e 100644 --- a/src/test/resources/integration.vcf +++ b/src/test/resources/integration.vcf @@ -2,7 +2,7 @@ ##FILTER= ##FORMAT= ##FORMAT= -##INFO= +##INFO= ##INFO= ##INFO= ##INFO= @@ -36,17 +36,17 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|1|AR,G|GENE2|EntrezGene|ID2||AD GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 -1 123460 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -1 123461 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|1|AD GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 -2 1 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 -3 2 empty_gene C G . PASS CSQ=G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 -4 123457 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5||XLR,G|GENE7|EntrezGene|ID7||XLD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=G|GENE6|EntrezGene|ID6||XLR GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 +1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP 1/0:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 +2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 +3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP 1/0:50 0/0:50 1/0:50 1/0:50 1/0:50 0/0:50 +4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 From 501617b27d54fdaf9c963b66e1e313e479568898 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 24 Sep 2024 08:34:03 +0200 Subject: [PATCH 07/28] Merge with main + reproducable IT tests --- .../vcf/inheritance/matcher/Annotator.java | 4 ++-- .../inheritance/matcher/InheritanceService.java | 8 +++++--- .../matcher/VcfRecordFactoryImpl.java | 2 ++ .../vcf/inheritance/matcher/model/GeneInfo.java | 7 ++++++- .../matcher/model/InheritanceGeneResult.java | 17 ++++++++++++++++- src/test/resources/expected_noParents.vcf | 2 +- src/test/resources/expected_noPed.vcf | 2 +- src/test/resources/expected_probands.vcf | 2 +- 8 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 0027658..ddfdcb3 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -70,7 +70,7 @@ private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype List VIC = new ArrayList<>(); List VIG = new ArrayList<>(); List VI = new ArrayList<>(); - for (InheritanceGeneResult inheritanceGeneResult : inheritanceResult.getInheritanceGeneResults()) { + inheritanceResult.getInheritanceGeneResults().stream().sorted().forEach(inheritanceGeneResult -> { String compounds = inheritanceGeneResult.getCompounds().isEmpty() ? "" : String.join("&", inheritanceGeneResult.getCompounds().stream().map(this::createKey).toList()); MatchEnum match = inheritanceGeneResult.getMatch(); VI.add(String.join("&", mapInheritanceModes(inheritanceGeneResult))); @@ -79,7 +79,7 @@ private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype if ((match == TRUE || match == POTENTIAL)) { VIG.add(inheritanceGeneResult.getGeneInfo().geneId()); } - } + }); genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", VI)); genotypeBuilder.attribute(INHERITANCE_MATCH, String.join(",", VIM)); genotypeBuilder.attribute(POSSIBLE_COMPOUND, String.join(",", VIC)); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index d023476..b1bd10d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -63,7 +63,7 @@ public void run(VcfReader vcfReader, RecordWriter recordWriter) { Map inheritanceResultMap = new HashMap<>(); for (Pedigree pedigree : pedigrees) { Map geneInheritanceResults = new HashMap<>(); - for (VariantGeneRecord variantGeneRecord : variantRecord.variantGeneRecords().values().stream().toList()) {//FIXME stream directly + variantRecord.variantGeneRecords().values().forEach(variantGeneRecord -> { InheritanceGeneResult geneInheritanceResult = InheritanceGeneResult.builder().geneInfo(variantGeneRecord.getGeneInfo()).build(); Set altAllelesForPedigree = getAltAlleles(variantGeneRecord, pedigree); //Only perform matching if a family member with a pathogenic allele is present @@ -83,7 +83,7 @@ public void run(VcfReader vcfReader, RecordWriter recordWriter) { } } } - if(!variantGeneRecord.getGeneInfo().geneId().isEmpty()) { + if (!variantGeneRecord.getGeneInfo().geneId().isEmpty()) { Set compounds = arCompoundChecker.check(vcfRecordGeneInfoMap, variantGeneRecord, pedigree); if (!compounds.isEmpty()) { geneInheritanceResult.setCompounds(compounds); @@ -91,11 +91,13 @@ public void run(VcfReader vcfReader, RecordWriter recordWriter) { Set pedigreeInheritanceMatches = geneInheritanceResult.getPedigreeInheritanceMatches(); pedigreeInheritanceMatches.add(new PedigreeInheritanceMatch(AR_C, !isCertain)); geneInheritanceResult.setPedigreeInheritanceMatches(pedigreeInheritanceMatches); + geneInheritanceResult.setCompounds(compounds); geneInheritanceResults.put(variantGeneRecord.getGeneInfo(), geneInheritanceResult); } } geneInheritanceResults.put(variantGeneRecord.getGeneInfo(), geneInheritanceResult); - } + }); + Map denovoResult = new HashMap<>(); pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java index 56a5dde..ff0bfa1 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java @@ -91,6 +91,8 @@ private Set mapGeneInheritance(String inheritanceString) { modes.add(InheritanceMode.XLR); modes.add(InheritanceMode.XLD); } + case "YL" -> modes.add(InheritanceMode.YL); + case "MT" -> modes.add(InheritanceMode.MT); default -> { //We ignore all the modes that are not used for matching. } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java index c05c5e9..cd4ecfd 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/GeneInfo.java @@ -1,6 +1,11 @@ package org.molgenis.vcf.inheritance.matcher.model; +import lombok.NonNull; + import java.util.Set; -public record GeneInfo(String geneId, String symbolSource, Set inheritanceModes) { +public record GeneInfo(String geneId, String symbolSource, Set inheritanceModes) implements Comparable { + public int compareTo(@NonNull GeneInfo geneInfo) { + return this.geneId.compareTo(geneInfo.geneId); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java index 3fd4bc2..77703b9 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java @@ -13,7 +13,7 @@ @Data @Builder -public class InheritanceGeneResult { +public class InheritanceGeneResult implements Comparable { @NonNull GeneInfo geneInfo; @@ -73,9 +73,24 @@ private static Boolean isMatch(Set pedigreeInheritance return true; } } + case YL -> { + if (geneInheritanceMode == YL) { + return true; + } + } + case MT -> { + if (geneInheritanceMode == MT) { + return true; + } + } default -> throw new UnexpectedEnumException(pedigreeInheritanceMatch.inheritanceMode()); } } return false; } + + @Override + public int compareTo(InheritanceGeneResult o) { + return geneInfo.compareTo(o.getGeneInfo()); + } } diff --git a/src/test/resources/expected_noParents.vcf b/src/test/resources/expected_noParents.vcf index 1da3786..f18256a 100644 --- a/src/test/resources/expected_noParents.vcf +++ b/src/test/resources/expected_noParents.vcf @@ -57,5 +57,5 @@ X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID9 ./.:50 0/0:50 1/0:50:YL:::ID9 ./.:50 0/0:50 Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID10 ./.:50 0/0:50 1/0:50:YL:::ID10 ./.:50 0/0:50 -Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11 .:50 0:50 1:50:YL:::ID11 .:50 0:50 +Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11:1 .:50 0:50 1:50:YL:::ID11:1 .:50 0:50 MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT:::ID12 .:50 0:50 1:50:MT:::ID12 .:50 0:50 diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index e1f73dc..bffe9c2 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -57,5 +57,5 @@ X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50:::::0 Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 -Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11 .:50:::::0 0:50:::::0 1:50:YL:::ID11 .:50:::::0 0:50:::::0 +Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11:1 .:50:::::0 0:50:::::0 1:50:YL:::ID11:1 .:50:::::0 0:50:::::0 MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT:::ID12 .:50:::::0 0:50:::::0 1:50:MT:::ID12 .:50:::::0 0:50:::::0 diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index 666b294..84fe471 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -57,5 +57,5 @@ X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL::1:ID9 ./.:50 0/0:50 1/0:50:YL:::ID9 ./.:50 0/0:50 Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL::1:ID10 ./.:50 0/0:50 1/0:50:YL:::ID10 ./.:50 0/0:50 -Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL::1:ID11 .:50 0:50 1:50:YL:::ID11 .:50 0:50 +Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL::1:ID11:1 .:50 0:50 1:50:YL:::ID11:1 .:50 0:50 MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT:::ID12 .:50 0:50 1:50:MT:::ID12 .:50 0:50 From b6bbc9322a2555d7948c269cf3a1f75c46d60b3c Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 24 Sep 2024 09:58:31 +0200 Subject: [PATCH 08/28] Deduplicate code --- .../matcher/checker/AdChecker.java | 48 ++------------ .../checker/AdNonPenetranceChecker.java | 62 ++++++++++--------- .../matcher/checker/ArChecker.java | 52 ++-------------- .../matcher/checker/ArCompoundChecker.java | 31 +--------- .../matcher/checker/CheckerUtils.java | 44 +++++++++++++ .../matcher/checker/DominantChecker.java | 35 +++++++++++ .../matcher/checker/InheritanceChecker.java | 31 ++++++---- .../matcher/checker/MtChecker.java | 51 ++------------- .../matcher/checker/XlChecker.java | 20 ------ .../matcher/checker/XldChecker.java | 50 +++------------ .../matcher/checker/XlrChecker.java | 50 +++------------ .../matcher/checker/YlChecker.java | 51 ++------------- 12 files changed, 168 insertions(+), 357 deletions(-) create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index b8b855e..dab32ab 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -11,13 +11,14 @@ import java.util.*; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; /** * Autosomal dominant (AD) inheritance pattern matcher */ @Component -public class AdChecker { +public class AdChecker extends DominantChecker { /** * Check whether the AD inheritance pattern could match for a variant in a pedigree */ @@ -30,19 +31,7 @@ public MatchEnum check( return checkFamily(variantGeneRecord, family); } - private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); - Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ - matches.add(POTENTIAL); - } - return merge(matches); - } - - private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); @@ -66,7 +55,7 @@ else if(genotype.isHomRef()){ return merge(matches); } - private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); @@ -81,33 +70,4 @@ private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map< } return merge(matches); } - - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { - return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } - } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java index b96492e..58b427a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java @@ -10,39 +10,45 @@ import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; -@Component -public class AdNonPenetranceChecker extends InheritanceChecker{ +import java.util.HashSet; +import java.util.Set; - public MatchEnum check( - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantGeneRecord)) { - return FALSE; - } +@Component +public class AdNonPenetranceChecker { - return checkFamily(variantGeneRecord, family); - } + public MatchEnum check( + VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantGeneRecord)) { + return FALSE; + } - MatchEnum checkSample(Sample sample, VariantGeneRecord variantGeneRecord) { - EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(sample.getPerson().getIndividualId()); - switch (sample.getPerson().getAffectedStatus()) { - case AFFECTED -> { - if(sampleGt.isHomRef()){ - return FALSE; + Set results = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + results.add(checkSample(sample, variantGeneRecord)); } - else if (sampleGt.isMixed()) { - return sampleGt.hasAlt() ? TRUE : POTENTIAL; - } else{ - return TRUE; + return CheckerUtils.merge(results); + } + + MatchEnum checkSample(Sample sample, VariantGeneRecord variantGeneRecord) { + EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(sample.getPerson().getIndividualId()); + switch (sample.getPerson().getAffectedStatus()) { + case AFFECTED -> { + if (sampleGt.isHomRef()) { + return FALSE; + } else if (sampleGt.isMixed()) { + return sampleGt.hasAlt() ? TRUE : POTENTIAL; + } else { + return TRUE; + } + } + case UNAFFECTED -> { + return TRUE; + } + case MISSING -> { + return POTENTIAL; + } + default -> throw new IllegalArgumentException(); } - } - case UNAFFECTED -> { - return TRUE; - } - case MISSING -> { - return POTENTIAL; - } - default -> throw new IllegalArgumentException(); } - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java index 44ff1d2..b07b0c5 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java @@ -1,5 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import htsjdk.variant.variantcontext.Allele; @@ -15,7 +16,7 @@ import java.util.*; @Component -public class ArChecker { +public class ArChecker extends InheritanceChecker { public MatchEnum check( VariantGeneRecord variantGeneRecord, Pedigree family) { @@ -26,50 +27,7 @@ public MatchEnum check( return checkFamily(variantGeneRecord, family); } - private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Map> membersByStatus = getMembersByStatus(family); - Set> affectedGenotypes = new HashSet<>(); - Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - Set affectedAltAlleles = new HashSet<>(); - affectedGenotypes.forEach(alleles -> alleles.stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); - if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { - matches.add(POTENTIAL); - } - return merge(matches); - } - - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { - return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } - } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; - } - - private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); @@ -87,11 +45,11 @@ private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Ma return merge(matches); } - private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set> affectedGenotypes) { + protected MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); - affectedGenotypes.add(genotype.getAlleles()); + affectedGenotypes.add(genotype); if (genotype.hasReference()) { return FALSE; } else if ((genotype.isMixed()) || genotype.isNoCall()) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index 94ca44a..d31b32e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -1,6 +1,8 @@ package org.molgenis.vcf.inheritance.matcher.checker; import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.getMembersByStatus; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import htsjdk.variant.variantcontext.Allele; @@ -130,33 +132,4 @@ private MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, VariantGene } return merge(matches); } - - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { - return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } - } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java new file mode 100644 index 0000000..fb5a862 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java @@ -0,0 +1,44 @@ +package org.molgenis.vcf.inheritance.matcher.checker; + +import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; +import org.molgenis.vcf.utils.sample.model.Pedigree; +import org.molgenis.vcf.utils.sample.model.Sample; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; + +public class CheckerUtils { + public static Map> getMembersByStatus(Pedigree family) { + Map> membersByStatus = new HashMap<>(); + Set affected = new HashSet<>(); + Set unAffected = new HashSet<>(); + Set missing = new HashSet<>(); + for (Sample sample : family.getMembers().values()) { + if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { + affected.add(sample); + } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { + unAffected.add(sample); + } else { + missing.add(sample); + } + } + membersByStatus.put(AffectedStatus.AFFECTED, affected); + membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); + membersByStatus.put(AffectedStatus.MISSING, missing); + return membersByStatus; + } + + public static MatchEnum merge(Set matches) { + if (matches.contains(FALSE)) { + return FALSE; + } else if (matches.contains(POTENTIAL)) { + return POTENTIAL; + } + return TRUE; + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java new file mode 100644 index 0000000..b9743e3 --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java @@ -0,0 +1,35 @@ +package org.molgenis.vcf.inheritance.matcher.checker; + +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; +import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; +import org.molgenis.vcf.utils.sample.model.Pedigree; +import org.molgenis.vcf.utils.sample.model.Sample; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.getMembersByStatus; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; +import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; + +public abstract class DominantChecker { + + MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ + matches.add(POTENTIAL); + } + return merge(matches); + } + + protected abstract MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); + + protected abstract MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java index 905618a..2e26122 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java @@ -1,31 +1,38 @@ package org.molgenis.vcf.inheritance.matcher.checker; +import htsjdk.variant.variantcontext.Allele; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; +import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.getMembersByStatus; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; public abstract class InheritanceChecker { - public MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Set results = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, variantGeneRecord)); + protected MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + Map> membersByStatus = getMembersByStatus(family); + Set affectedGenotypes = new HashSet<>(); + Set matches = new HashSet<>(); + matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + Set affectedAltAlleles = new HashSet<>(); + affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); + matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); + if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { + matches.add(POTENTIAL); } - if(results.contains(FALSE)){ - return FALSE; - }else if(results.contains(POTENTIAL)){ - return POTENTIAL; - } - return TRUE; + return merge(matches); } - abstract MatchEnum checkSample(Sample sample, VariantGeneRecord variantGeneRecord); - + protected abstract MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAltAlleles); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java index 5915408..41f05ea 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java @@ -10,15 +10,15 @@ import org.molgenis.vcf.utils.sample.model.Sample; import org.springframework.stereotype.Component; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; @Component -public class MtChecker { +public class MtChecker extends InheritanceChecker { public MatchEnum check( VariantGeneRecord variantGeneRecord, Pedigree family) { if (!VariantContextUtils.onChromosomeMt(variantGeneRecord)) { @@ -28,21 +28,7 @@ public MatchEnum check( return checkFamily(variantGeneRecord, family); } - private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); - Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - Set affectedAltAlleles = new HashSet<>(); - affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); - if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { - matches.add(POTENTIAL); - } - return merge(matches); - } - - private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); @@ -59,7 +45,7 @@ private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Ma return merge(matches); } - private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); @@ -74,33 +60,4 @@ private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map< } return merge(matches); } - - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { - return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } - } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java deleted file mode 100644 index 9e90930..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlChecker.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher.checker; - -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeX; -import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; - -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; -import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; -import org.molgenis.vcf.utils.sample.model.Pedigree; - -public abstract class XlChecker{ - - public MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!onChromosomeX(variantGeneRecord)) { - return FALSE; - } - return checkFamily(variantGeneRecord, family); - } - - protected abstract MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family); -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index 2df1f70..aa670c4 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -10,24 +10,21 @@ import java.util.*; +import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeX; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; @Component -public class XldChecker extends XlChecker { +public class XldChecker extends DominantChecker { - public MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); - Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ - matches.add(POTENTIAL); + public MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!onChromosomeX(variantGeneRecord)) { + return FALSE; } - return merge(matches); + return checkFamily(variantGeneRecord, family); } - private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); @@ -51,7 +48,7 @@ else if(!genotype.hasAlt() && !genotype.isMixed() || (genotype.hasReference() && return merge(matches); } - private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); @@ -66,33 +63,4 @@ private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map< } return merge(matches); } - - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { - return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } - } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; - } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index 9b171df..7d13712 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -11,55 +11,21 @@ import java.util.*; +import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeX; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; @Component -public class XlrChecker extends XlChecker { +public class XlrChecker extends InheritanceChecker { - protected MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); - Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - Set affectedAltAlleles = new HashSet<>(); - affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); - if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { - matches.add(POTENTIAL); - } - return merge(matches); - } - - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { + public MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree family) { + if (!onChromosomeX(variantGeneRecord)) { return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; + return checkFamily(variantGeneRecord, family); } - private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); @@ -75,7 +41,7 @@ private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Ma return merge(matches); } - private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java index b5537d8..d6360a7 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java @@ -11,17 +11,17 @@ import org.molgenis.vcf.utils.sample.model.Sex; import org.springframework.stereotype.Component; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.utils.sample.model.Sex.FEMALE; import static org.molgenis.vcf.utils.sample.model.Sex.MALE; @Component -public class YlChecker { +public class YlChecker extends InheritanceChecker { public MatchEnum check( VariantGeneRecord variantGeneRecord, Pedigree family) { if (!VariantContextUtils.onChromosomeY(variantGeneRecord)) { @@ -31,21 +31,7 @@ public MatchEnum check( return checkFamily(variantGeneRecord, family); } - private MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { - Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); - Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - Set affectedAltAlleles = new HashSet<>(); - affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); - if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { - matches.add(POTENTIAL); - } - return merge(matches); - } - - private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); @@ -66,7 +52,7 @@ private static MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Ma return merge(matches); } - private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); @@ -85,35 +71,6 @@ private static MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map< return merge(matches); } - private static MatchEnum merge(Set matches) { - if (matches.contains(FALSE)) { - return FALSE; - } else if (matches.contains(POTENTIAL)) { - return POTENTIAL; - } - return TRUE; - } - - private Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); - Set affected = new HashSet<>(); - Set unAffected = new HashSet<>(); - Set missing = new HashSet<>(); - for (Sample sample : family.getMembers().values()) { - if (sample.getPerson().getAffectedStatus() == AffectedStatus.AFFECTED) { - affected.add(sample); - } else if (sample.getPerson().getAffectedStatus() == AffectedStatus.UNAFFECTED) { - unAffected.add(sample); - } else { - missing.add(sample); - } - } - membersByStatus.put(AffectedStatus.AFFECTED, affected); - membersByStatus.put(AffectedStatus.UNAFFECTED, unAffected); - membersByStatus.put(AffectedStatus.MISSING, missing); - return membersByStatus; - } - protected static Sex getSex(Sample sample, EffectiveGenotype genotype) { if (sample.getPerson().getSex() == Sex.UNKNOWN) { //UNKNOWN? use best guess based on number of alleles From da2f29ae8a330c084dd3704c5272f0b850af6d5b Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 24 Sep 2024 11:29:33 +0200 Subject: [PATCH 09/28] Fix Sonar issues --- .../vcf/inheritance/matcher/Annotator.java | 28 ++++++------- .../matcher/AppCommandLineRunner.java | 2 +- .../matcher/PedigreeInheritanceChecker.java | 16 +++---- .../matcher/VcfRecordFactoryImpl.java | 12 +++--- .../matcher/checker/AdChecker.java | 9 +--- .../matcher/checker/CheckerUtils.java | 10 ++--- .../matcher/checker/DominantChecker.java | 11 +++++ .../matcher/checker/XldChecker.java | 9 +--- .../matcher/model/VcfRecordGenes.java | 4 +- .../PedigreeInheritanceCheckerTest.java | 42 +++++++++---------- .../matcher/checker/DeNovoCheckerTest.java | 4 +- .../matcher/util/VariantContextTestUtil.java | 8 ++-- 12 files changed, 74 insertions(+), 81 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index ddfdcb3..7d8f953 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -66,24 +66,24 @@ VariantContext annotateInheritance(VariantRecord variantRecord, Collection VIM = new ArrayList<>(); - List VIC = new ArrayList<>(); - List VIG = new ArrayList<>(); - List VI = new ArrayList<>(); + List vim = new ArrayList<>(); + List vic = new ArrayList<>(); + List vig = new ArrayList<>(); + List vi = new ArrayList<>(); inheritanceResult.getInheritanceGeneResults().stream().sorted().forEach(inheritanceGeneResult -> { String compounds = inheritanceGeneResult.getCompounds().isEmpty() ? "" : String.join("&", inheritanceGeneResult.getCompounds().stream().map(this::createKey).toList()); MatchEnum match = inheritanceGeneResult.getMatch(); - VI.add(String.join("&", mapInheritanceModes(inheritanceGeneResult))); - VIM.add(mapInheritanceMatch(match)); - VIC.add(compounds); + vi.add(String.join("&", mapInheritanceModes(inheritanceGeneResult))); + vim.add(mapInheritanceMatch(match)); + vic.add(compounds); if ((match == TRUE || match == POTENTIAL)) { - VIG.add(inheritanceGeneResult.getGeneInfo().geneId()); + vig.add(inheritanceGeneResult.getGeneInfo().geneId()); } }); - genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", VI)); - genotypeBuilder.attribute(INHERITANCE_MATCH, String.join(",", VIM)); - genotypeBuilder.attribute(POSSIBLE_COMPOUND, String.join(",", VIC)); - genotypeBuilder.attribute(MATCHING_GENES, String.join(",", VIG)); + genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", vi)); + genotypeBuilder.attribute(INHERITANCE_MATCH, String.join(",", vim)); + genotypeBuilder.attribute(POSSIBLE_COMPOUND, String.join(",", vic)); + genotypeBuilder.attribute(MATCHING_GENES, String.join(",", vig)); genotypeBuilder.attribute(DENOVO, mapDenovoValue(inheritanceResult, sample)); return genotypeBuilder.make(); } @@ -116,7 +116,7 @@ private Set mapInheritanceModes(InheritanceGeneResult inheritanceResult) } private String createKey(CompoundCheckResult result) { - VariantGeneRecord record = result.getPossibleCompound(); - return String.format("%s_%s_%s_%s", record.getContig(), record.getStart(), record.getReference().getBaseString(), record.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); + VariantGeneRecord variantGeneRecord = result.getPossibleCompound(); + return String.format("%s_%s_%s_%s", variantGeneRecord.getContig(), variantGeneRecord.getStart(), variantGeneRecord.getReference().getBaseString(), variantGeneRecord.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java index 6e00b8f..4bba679 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java @@ -31,7 +31,7 @@ class AppCommandLineRunner implements CommandLineRunner { AppCommandLineRunner( @Value("${app.name}") String appName, - @Value("${app.version}") String appVersion, AppRunnerFactoryImpl appRunnerFactoryImpl, App app) { + @Value("${app.version}") String appVersion, AppRunnerFactoryImpl appRunnerFactoryImpl) { this.appName = requireNonNull(appName); this.appVersion = requireNonNull(appVersion); this.appRunnerFactoryImpl = requireNonNull(appRunnerFactoryImpl); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java index b00829a..2d3185a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java @@ -27,16 +27,16 @@ public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, this.ylChecker = ylChecker; } - MatchEnum check(VariantGeneRecord record, Pedigree pedigree, InheritanceMode mode) { + MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree pedigree, InheritanceMode mode) { MatchEnum result; switch(mode){ - case AD -> result = adChecker.check(record, pedigree); - case AD_IP -> result = adNonPenetranceChecker.check(record, pedigree); - case AR -> result = arChecker.check(record, pedigree); - case XLR -> result = xlrChecker.check(record, pedigree); - case XLD -> result = xldChecker.check(record, pedigree); - case MT -> result = mtChecker.check(record, pedigree); - case YL -> result = ylChecker.check(record, pedigree); + case AD -> result = adChecker.check(variantGeneRecord, pedigree); + case AD_IP -> result = adNonPenetranceChecker.check(variantGeneRecord, pedigree); + case AR -> result = arChecker.check(variantGeneRecord, pedigree); + case XLR -> result = xlrChecker.check(variantGeneRecord, pedigree); + case XLD -> result = xldChecker.check(variantGeneRecord, pedigree); + case MT -> result = mtChecker.check(variantGeneRecord, pedigree); + case YL -> result = ylChecker.check(variantGeneRecord, pedigree); default -> throw new UnexpectedEnumException(mode); } return result; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java index ff0bfa1..66a5256 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java @@ -35,7 +35,7 @@ private Set getVcfGeneInfos(VariantContext variantContext) { String[] vepSplit = vepValue.split("\\|", -1); String geneId = vepSplit[vepMetadata.getGeneIndex()]; String symbolSource = vepSplit[vepMetadata.getGeneSourceIndex()]; - Set inheritanceModes = vepMetadata.getInheritanceIndex() != -1 ? mapGeneInheritance(vepSplit[vepMetadata.getInheritanceIndex()]): emptySet(); + Set inheritanceModes = vepMetadata.getInheritanceIndex() != -1 ? mapGeneInheritance(vepSplit[vepMetadata.getInheritanceIndex()]) : emptySet(); result.add(new GeneInfo(geneId, symbolSource, inheritanceModes)); } return result; @@ -46,7 +46,7 @@ private Set getPathogenicAlleles(VariantContext variantContext, VepMetad for (int i = 1; i <= variantContext.getAlternateAlleles().size(); i++) { Allele allele = variantContext.getAlleles().get(i); - if(isAllelePathogenic(variantContext, vepMetadata, i, geneInfo, pathogenicClasses)) { + if (isAllelePathogenic(variantContext, vepMetadata, i, geneInfo, pathogenicClasses)) { pathogenicAlleles.add(allele); } } @@ -54,7 +54,7 @@ private Set getPathogenicAlleles(VariantContext variantContext, VepMetad } public boolean isAllelePathogenic(VariantContext variantContext, VepMetadata vepMetadata, int alleleIndex, GeneInfo geneInfo, Set pathogenicClasses) { - if(pathogenicClasses.isEmpty()){ + if (pathogenicClasses.isEmpty()) { return true; } if ((vepMetadata.getAlleleNumIndex() == -1 || vepMetadata.getClassIndex() == -1)) { @@ -65,10 +65,8 @@ public boolean isAllelePathogenic(VariantContext variantContext, VepMetadata vep for (String vepValue : vepValues) { String[] vepSplit = vepValue.split("\\|", -1); int csqAlleleIndex = Integer.parseInt(vepSplit[vepMetadata.getAlleleNumIndex()]); - if (csqAlleleIndex == alleleIndex) { - if (geneInfo.geneId().equals(vepSplit[vepMetadata.getGeneIndex()])) { - result = pathogenicClasses.contains(vepSplit[vepMetadata.getClassIndex()]); - } + if (csqAlleleIndex == alleleIndex && geneInfo.geneId().equals(vepSplit[vepMetadata.getGeneIndex()])) { + result = pathogenicClasses.contains(vepSplit[vepMetadata.getClassIndex()]); } } return result; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index dab32ab..f623d0d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -42,14 +42,7 @@ else if(genotype.isHomRef()){ matches.add(TRUE); } else { - for (EffectiveGenotype affectedGenotype : affectedGenotypes) { - if (affectedGenotype.hasAlt() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( - allele -> genotype.getAlleles().contains(allele))) { - matches.add(FALSE); - } else { - matches.add(POTENTIAL); - } - } + checkAffectedGenotypes(affectedGenotypes, matches, genotype); } } return merge(matches); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java index fb5a862..b65d565 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java @@ -5,16 +5,16 @@ import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; public class CheckerUtils { + + private CheckerUtils(){}; + public static Map> getMembersByStatus(Pedigree family) { - Map> membersByStatus = new HashMap<>(); + Map> membersByStatus = new EnumMap<>(AffectedStatus.class); Set affected = new HashSet<>(); Set unAffected = new HashSet<>(); Set missing = new HashSet<>(); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java index b9743e3..2ec6b19 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java @@ -29,6 +29,17 @@ MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { return merge(matches); } + static void checkAffectedGenotypes(Set affectedGenotypes, Set matches, EffectiveGenotype genotype) { + for (EffectiveGenotype affectedGenotype : affectedGenotypes) { + if (affectedGenotype.hasAlt() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( + allele -> genotype.getAlleles().contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); + } + } + } + protected abstract MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); protected abstract MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index aa670c4..3bfd2f4 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -35,14 +35,7 @@ else if(!genotype.hasAlt() && !genotype.isMixed() || (genotype.hasReference() && matches.add(TRUE); } else { - for (EffectiveGenotype affectedGenotype : affectedGenotypes) { - if (affectedGenotype.hasAlt() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( - allele -> genotype.getAlleles().contains(allele))) { - matches.add(FALSE); - } else{ - matches.add(POTENTIAL); - } - } + checkAffectedGenotypes(affectedGenotypes, matches, genotype); } } return merge(matches); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java index fbc5b70..1e5aaba 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/VcfRecordGenes.java @@ -3,11 +3,9 @@ import lombok.Builder; import lombok.Data; import java.util.Map; + @Data @Builder public class VcfRecordGenes { Map genes; - //FIXME: is this used? - @Builder.Default - boolean containsVcWithoutGene = false; } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java index c5c0f1f..d273db5 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java @@ -46,70 +46,70 @@ void setUp() { @Test void testAdPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(adChecker.check(record, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.AD); + when(adChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.AD); assertEquals(POTENTIAL, actual); } @Test void testAdIpTrue() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(adNonPenetranceChecker.check(record, family)).thenReturn(TRUE); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.AD_IP); + when(adNonPenetranceChecker.check(variantGeneRecord, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.AD_IP); assertEquals(TRUE, actual); } @Test void testArPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(arChecker.check(record, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.AR); + when(arChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.AR); assertEquals(POTENTIAL, actual); } @Test void testXldFalse() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(xldChecker.check(record, family)).thenReturn(FALSE); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.XLD); + when(xldChecker.check(variantGeneRecord, family)).thenReturn(FALSE); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.XLD); assertEquals(FALSE, actual); } @Test void testXlrPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(xlrChecker.check(record, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.XLR); + when(xlrChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.XLR); assertEquals(POTENTIAL, actual); } @Test void testYlTrue() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(ylChecker.check(record, family)).thenReturn(TRUE); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.YL); + when(ylChecker.check(variantGeneRecord, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.YL); assertEquals(TRUE, actual); } @Test void testMtPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord record = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); Pedigree family = mock(Pedigree.class); - when(mtChecker.check(record, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(record, family, InheritanceMode.MT); + when(mtChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.MT); assertEquals(POTENTIAL, actual); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java index b3b6578..a4225e3 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java @@ -54,12 +54,12 @@ private static Stream provideTestCases() throws IOException { Pedigree family = PedigreeTestUtil .createFamily(probandSex, AffectedStatus.MISSING, AffectedStatus.MISSING, AffectedStatus.MISSING, "FAM001"); - VariantGeneRecord record = VariantContextTestUtil + VariantGeneRecord variantGeneRecord = VariantContextTestUtil .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), createGenotype("Father", fatherGt), createGenotype("Mother", motherGt)), "", chrom); - return Arguments.of(new VariantRecord(Map.of(record.getGeneInfo(), record), record.unwrap(),InheritanceResult.builder().build()), family, expected, testName); + return Arguments.of(new VariantRecord(Map.of(variantGeneRecord.getGeneInfo(), variantGeneRecord), variantGeneRecord.unwrap(),InheritanceResult.builder().build()), family, expected, testName); }); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java index a912f9d..4564719 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java @@ -18,18 +18,18 @@ public class VariantContextTestUtil { public static final Allele REF = Allele.REF_T; - public static VariantGeneRecord createVariantContext(List genotypes, String VepData) { - return createVariantContext(genotypes, VepData, "1"); + public static VariantGeneRecord createVariantContext(List genotypes, String vepData) { + return createVariantContext(genotypes, vepData, "1"); } - public static VariantGeneRecord createVariantContext(List genotypes, String VepData, String contig) { + public static VariantGeneRecord createVariantContext(List genotypes, String vepData, String contig) { VariantContextBuilder builder = new VariantContextBuilder(); builder.chr(contig); builder.start(12345); builder.stop(12345); builder.alleles(Arrays.asList(REF, ALT_A, Allele.ALT_G, Allele.ALT_C, Allele.ALT_N)); builder.genotypes(genotypes); - builder.attribute("CSQ", VepData); + builder.attribute("CSQ", vepData); return new VariantGeneRecord(builder.make(), Set.of(ALT_A,ALT_G,ALT_N), new GeneInfo("GENE1", "SOURCE", emptySet())); } From aa4fe064e6a49cd631e81995233b801de20b65e4 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 24 Sep 2024 15:37:13 +0200 Subject: [PATCH 10/28] Refactor / simplify / Sonar issues --- .../vcf/inheritance/matcher/Annotator.java | 137 +++++++++++++++--- .../matcher/EffectiveGenotype.java | 8 +- .../matcher/InheritanceService.java | 126 +++++++++------- .../matcher/PedigreeInheritanceChecker.java | 16 +- .../matcher/VariantContextUtils.java | 10 +- .../matcher/VariantGeneRecord.java | 56 ------- .../inheritance/matcher/VariantRecord.java | 38 ++++- .../matcher/VcfRecordFactoryImpl.java | 19 +-- .../vcf/inheritance/matcher/VepMetadata.java | 14 +- .../matcher/checker/AdChecker.java | 20 +-- .../checker/AdNonPenetranceChecker.java | 20 +-- .../matcher/checker/ArChecker.java | 20 +-- .../matcher/checker/ArCompoundChecker.java | 122 +++++++++------- .../matcher/checker/CheckerUtils.java | 2 +- .../matcher/checker/DeNovoChecker.java | 56 ++++--- .../matcher/checker/DominantChecker.java | 14 +- .../matcher/checker/InheritanceChecker.java | 12 +- .../matcher/checker/MtChecker.java | 20 +-- .../matcher/checker/XldChecker.java | 22 +-- .../matcher/checker/XlrChecker.java | 20 +-- .../matcher/checker/YlChecker.java | 56 +++---- .../matcher/model/CompoundCheckResult.java | 4 +- .../matcher/model/InheritanceGeneResult.java | 96 ------------ .../matcher/model/InheritanceResult.java | 9 +- .../matcher/util/InheritanceUtils.java | 4 +- .../PedigreeInheritanceCheckerTest.java | 42 +++--- .../matcher/VariantContextUtilsTest.java | 2 +- .../matcher/checker/AdCheckerTest.java | 6 +- .../matcher/checker/AdNonPenCheckerTest.java | 11 +- .../matcher/checker/ArCheckerTest.java | 6 +- .../checker/ArCompoundCheckerTest.java | 32 +++- .../matcher/checker/DeNovoCheckerTest.java | 55 ++++--- .../matcher/checker/MtCheckerTest.java | 6 +- .../matcher/checker/XldCheckerTest.java | 6 +- .../matcher/checker/XlrCheckerTest.java | 6 +- .../matcher/checker/YlCheckerTest.java | 6 +- .../matcher/util/VariantContextTestUtil.java | 8 +- 37 files changed, 562 insertions(+), 545 deletions(-) delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceGeneResult.java diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 7d8f953..84439d7 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -1,5 +1,6 @@ package org.molgenis.vcf.inheritance.matcher; +import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.utils.utils.HeaderUtils.fixVcfFilterHeaderLines; import static org.molgenis.vcf.utils.utils.HeaderUtils.fixVcfFormatHeaderLines; @@ -55,39 +56,56 @@ VariantContext annotateInheritance(VariantRecord variantRecord, Collection probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(sample -> { - Genotype genotype = variantRecord.getGenotype(sample.getPerson().getIndividualId()); + EffectiveGenotype effectiveGenotype = variantRecord.getGenotype(sample.getPerson().getIndividualId()); + Genotype genotype = effectiveGenotype != null ? effectiveGenotype.unwrap() : null; if (inheritanceResultMap.containsKey(pedigree) && genotype != null) { - genotypesContext.replace(annotateGenotype(inheritanceResultMap.get(pedigree), genotype, sample)); + genotypesContext.replace(annotateGenotype(inheritanceResultMap.get(pedigree), genotype, sample, variantRecord)); } }); } return variantContextBuilder.genotypes(genotypesContext).make(); } - private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype genotype, Sample sample) { + private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype genotype, Sample sample, VariantRecord variantRecord) { GenotypeBuilder genotypeBuilder = new GenotypeBuilder(genotype); - List vim = new ArrayList<>(); - List vic = new ArrayList<>(); List vig = new ArrayList<>(); - List vi = new ArrayList<>(); - inheritanceResult.getInheritanceGeneResults().stream().sorted().forEach(inheritanceGeneResult -> { - String compounds = inheritanceGeneResult.getCompounds().isEmpty() ? "" : String.join("&", inheritanceGeneResult.getCompounds().stream().map(this::createKey).toList()); - MatchEnum match = inheritanceGeneResult.getMatch(); - vi.add(String.join("&", mapInheritanceModes(inheritanceGeneResult))); - vim.add(mapInheritanceMatch(match)); - vic.add(compounds); - if ((match == TRUE || match == POTENTIAL)) { - vig.add(inheritanceGeneResult.getGeneInfo().geneId()); - } - }); + Set compounds = getCompoundStrings(inheritanceResult.getCompounds()); + String vic = inheritanceResult.getCompounds().isEmpty() ? "" : String.join(",", compounds); + MatchEnum match = getMatch(inheritanceResult, variantRecord); + Set vi = mapInheritanceModes(inheritanceResult); + String vim = mapInheritanceMatch(match); + if ((match == TRUE || match == POTENTIAL)) { + vig = getMatchingGenes(inheritanceResult.getPedigreeInheritanceMatches(), variantRecord.geneInfos(), inheritanceResult.getCompounds()); + } + genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", vi)); - genotypeBuilder.attribute(INHERITANCE_MATCH, String.join(",", vim)); - genotypeBuilder.attribute(POSSIBLE_COMPOUND, String.join(",", vic)); + genotypeBuilder.attribute(INHERITANCE_MATCH, vim); + genotypeBuilder.attribute(POSSIBLE_COMPOUND, vic); genotypeBuilder.attribute(MATCHING_GENES, String.join(",", vig)); genotypeBuilder.attribute(DENOVO, mapDenovoValue(inheritanceResult, sample)); return genotypeBuilder.make(); } + private Set getCompoundStrings(Map> compounds) { + Set result = new HashSet<>(); + compounds.values().forEach(compoundsForGene -> compoundsForGene.forEach(compound -> result.add(createKey(compound)))); + return result; + } + + private List getMatchingGenes(Set pedigreeInheritanceMatches, Set geneInfos, Map> compounds) { + List results = new ArrayList<>(); + for (PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { + for (GeneInfo geneInfo : geneInfos) { + if (geneInfo.inheritanceModes().stream().anyMatch(geneMode -> isMatch(geneMode, + pedigreeInheritanceMatch.inheritanceMode())) && pedigreeInheritanceMatch.inheritanceMode() != AR_C + || !compounds.get(geneInfo).isEmpty()) { + results.add(geneInfo.geneId()); + } + } + } + return results; + } + private static String mapDenovoValue(InheritanceResult inheritanceResult, Sample sample) { return switch (inheritanceResult.getDenovo().get(sample)) { case TRUE -> "1"; @@ -107,7 +125,7 @@ private static String mapInheritanceMatch(MatchEnum match) { return inheritanceMatch; } - private Set mapInheritanceModes(InheritanceGeneResult inheritanceResult) { + private Set mapInheritanceModes(InheritanceResult inheritanceResult) { Set result = new HashSet<>(); for (PedigreeInheritanceMatch pedigreeInheritanceMatch : inheritanceResult.getPedigreeInheritanceMatches()) { result.add(pedigreeInheritanceMatch.inheritanceMode().name()); @@ -116,7 +134,84 @@ private Set mapInheritanceModes(InheritanceGeneResult inheritanceResult) } private String createKey(CompoundCheckResult result) { - VariantGeneRecord variantGeneRecord = result.getPossibleCompound(); - return String.format("%s_%s_%s_%s", variantGeneRecord.getContig(), variantGeneRecord.getStart(), variantGeneRecord.getReference().getBaseString(), variantGeneRecord.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); + VariantRecord variantRecord = result.getPossibleCompound(); + return String.format("%s_%s_%s_%s", variantRecord.getContig(), variantRecord.getStart(), variantRecord.getReference().getBaseString(), variantRecord.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); + } + + /** + * If there is a match between sample inheritance modes and gene inheritance modes: + * - inheritance match is true + * If there are no matches between sample inheritance modes and gene inheritance modes: + * - inheritance match is unknown ifa gene has unknown inheritance pattern. + * - inheritance match is false if a gene has known (but mismatching) inheritance pattern. + */ + public MatchEnum getMatch(InheritanceResult inheritanceResult, VariantRecord variantRecord) { + //If no inheritance pattern is suitable for the sample, regardless of the gene: inheritance match is false. + Set pedigreeInheritanceMatches = inheritanceResult.getPedigreeInheritanceMatches(); + if (pedigreeInheritanceMatches.isEmpty()) { + return FALSE; + } + boolean containsUnknownGene = variantRecord.geneInfos().isEmpty() || variantRecord.geneInfos().stream().anyMatch(geneInfo -> geneInfo.inheritanceModes().isEmpty()); + + Set result = new HashSet<>(); + for (GeneInfo geneInfo : variantRecord.geneInfos()) { + if (geneInfo.inheritanceModes().stream() + .anyMatch(geneInheritanceMode -> isMatch(pedigreeInheritanceMatches, geneInheritanceMode))) { + if (pedigreeInheritanceMatches.stream().anyMatch(pedigreeInheritanceMatch -> !pedigreeInheritanceMatch.isUncertain())) { + result.add(TRUE); + } else { + result.add(POTENTIAL); + } + } + } + if (result.contains(TRUE)) { + return TRUE; + } + if (result.contains(POTENTIAL) || containsUnknownGene) { + return POTENTIAL; + } + return FALSE; + } + + private static Boolean isMatch(Set pedigreeInheritanceMatches, InheritanceMode geneInheritanceMode) { + boolean isMatch = false; + for (PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { + InheritanceMode pedigreeInheritanceMode = pedigreeInheritanceMatch.inheritanceMode(); + isMatch = isMatch(geneInheritanceMode, pedigreeInheritanceMode); + } + return isMatch; } + + private static boolean isMatch(InheritanceMode geneInheritanceMode, InheritanceMode pedigreeInheritanceMode) { + switch (pedigreeInheritanceMode) { + case AD, AD_IP -> { + if (geneInheritanceMode == AD) { + return true; + } + } + case AR, AR_C -> { + if (geneInheritanceMode == AR) { + return true; + } + } + case XLR, XLD -> { + if (geneInheritanceMode == XL) { + return true; + } + } + case YL -> { + if (geneInheritanceMode == YL) { + return true; + } + } + case MT -> { + if (geneInheritanceMode == MT) { + return true; + } + } + default -> throw new UnexpectedEnumException(pedigreeInheritanceMode); + } + return false; + } + } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java index 8506d5a..6ecff48 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java @@ -58,11 +58,15 @@ public boolean hasReference() { return genotype.getAlleles().stream().anyMatch(Allele::isReference); } - public boolean hasAlt() { - return genotype.getAlleles().stream().anyMatch(allele -> allele.isNonReference() && allele.isCalled()); + public boolean hasAltAllele() { + return genotype.hasAltAllele(); } public boolean isHom() { return genotype.isHom(); } + + public boolean isHet() { + return genotype.isHet(); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index b1bd10d..9b78188 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -47,76 +47,90 @@ public void run(VcfReader vcfReader, RecordWriter recordWriter) { VCFHeader newHeader = annotator.annotateHeader(vcfReader.getFileHeader()); recordWriter.writeHeader(newHeader); - Map> vcfRecordGeneInfoMap = new HashMap<>(); + Map> vcfRecordGeneInfoMap = new HashMap<>(); List variantRecords = vcfReader.stream().toList(); for (VariantRecord variantRecord : variantRecords) { - variantRecord.variantGeneRecords().values().forEach(variantGeneRecord -> { - //Only perform matching if a pathogenic or vus allele is present - if (!variantGeneRecord.getGeneInfo().geneId().isEmpty() && !variantGeneRecord.getPathogenicAlleles().isEmpty()) { - addToVcfRecordMap(variantGeneRecord, vcfRecordGeneInfoMap); - } - }); + //Only perform matching if a pathogenic or vus allele is present + if (!variantRecord.pathogenicAlleles().isEmpty()) { + addToVcfRecordMap(variantRecord, vcfRecordGeneInfoMap); + } } for (VariantRecord variantRecord : variantRecords) { - Map inheritanceResultMap = new HashMap<>(); - for (Pedigree pedigree : pedigrees) { - Map geneInheritanceResults = new HashMap<>(); - variantRecord.variantGeneRecords().values().forEach(variantGeneRecord -> { - InheritanceGeneResult geneInheritanceResult = InheritanceGeneResult.builder().geneInfo(variantGeneRecord.getGeneInfo()).build(); - Set altAllelesForPedigree = getAltAlleles(variantGeneRecord, pedigree); - //Only perform matching if a family member with a pathogenic allele is present - if (altAllelesForPedigree.stream().anyMatch(allele -> variantGeneRecord.getPathogenicAlleles().contains(allele))) { - addToVcfRecordMap(variantGeneRecord, vcfRecordGeneInfoMap); - Set modes = Set.of(AD, AR, XLD, XLR, MT, YL); - modes.forEach(mode -> { - MatchEnum isMatch = pedigreeInheritanceChecker.check(variantGeneRecord, pedigree, mode); - if (isMatch != FALSE) { - geneInheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(mode, isMatch == POTENTIAL)); - } - }); - if (geneInheritanceResult.getPedigreeInheritanceMatches().stream().noneMatch(match -> match.inheritanceMode() == AD)) { - MatchEnum isAdIpMatch = pedigreeInheritanceChecker.check(variantGeneRecord, pedigree, AD_IP); - if (isAdIpMatch != FALSE) { - geneInheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(AD_IP, isAdIpMatch == POTENTIAL)); - } - } - } - if (!variantGeneRecord.getGeneInfo().geneId().isEmpty()) { - Set compounds = arCompoundChecker.check(vcfRecordGeneInfoMap, variantGeneRecord, pedigree); - if (!compounds.isEmpty()) { - geneInheritanceResult.setCompounds(compounds); - boolean isCertain = compounds.stream().anyMatch(CompoundCheckResult::isCertain); - Set pedigreeInheritanceMatches = geneInheritanceResult.getPedigreeInheritanceMatches(); - pedigreeInheritanceMatches.add(new PedigreeInheritanceMatch(AR_C, !isCertain)); - geneInheritanceResult.setPedigreeInheritanceMatches(pedigreeInheritanceMatches); - geneInheritanceResult.setCompounds(compounds); - geneInheritanceResults.put(variantGeneRecord.getGeneInfo(), geneInheritanceResult); - } + matchVariantRecord(recordWriter, variantRecord, pedigrees, vcfRecordGeneInfoMap); + } + } + + private void matchVariantRecord(RecordWriter recordWriter, VariantRecord variantRecord, Collection pedigrees, Map> vcfRecordGeneInfoMap) { + Map inheritanceResultMap = new HashMap<>(); + matchPedigree(variantRecord, pedigrees, vcfRecordGeneInfoMap, inheritanceResultMap); + + VariantContext annotatedVc = annotator.annotateInheritance(variantRecord, pedigrees, inheritanceResultMap, probands); + recordWriter.add(annotatedVc); + } + + private void matchPedigree(VariantRecord variantRecord, Collection pedigrees, Map> vcfRecordGeneInfoMap, Map inheritanceResultMap) { + for (Pedigree pedigree : pedigrees) { + InheritanceResult inheritanceResult = InheritanceResult.builder().build(); + Set altAllelesForPedigree = getAltAlleles(variantRecord, pedigree); + //Only perform matching if a family member with a pathogenic allele is present + if (altAllelesForPedigree.stream().anyMatch(allele -> variantRecord.pathogenicAlleles().contains(allele))) { + addToVcfRecordMap(variantRecord, vcfRecordGeneInfoMap); + Set modes = Set.of(AD, AR, XLD, XLR, MT, YL); + modes.forEach(mode -> { + MatchEnum isMatch = pedigreeInheritanceChecker.check(variantRecord, pedigree, mode); + if (isMatch != FALSE) { + inheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(mode, isMatch == POTENTIAL)); } - geneInheritanceResults.put(variantGeneRecord.getGeneInfo(), geneInheritanceResult); }); + if (inheritanceResult.getPedigreeInheritanceMatches().stream().noneMatch(match -> match.inheritanceMode() == AD)) { + MatchEnum isAdIpMatch = pedigreeInheritanceChecker.check(variantRecord, pedigree, AD_IP); + if (isAdIpMatch != FALSE) { + inheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(AD_IP, isAdIpMatch == POTENTIAL)); + } + } + } + matchCompounds(variantRecord, vcfRecordGeneInfoMap, pedigree, inheritanceResult); + + Map denovoResult = new HashMap<>(); + pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> + denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); + inheritanceResult.setDenovo(denovoResult); + inheritanceResultMap.put(pedigree, inheritanceResult); + } + } - Map denovoResult = new HashMap<>(); - pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> - denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); - InheritanceResult inheritanceResult = InheritanceResult.builder().build(); - inheritanceResult.setInheritanceGeneResults(geneInheritanceResults.values()); - inheritanceResult.setDenovo(denovoResult); - inheritanceResultMap.put(pedigree, inheritanceResult); + private void matchCompounds(VariantRecord variantRecord, Map> vcfRecordGeneInfoMap, Pedigree pedigree, InheritanceResult inheritanceResult) { + Map> compoundsMap = arCompoundChecker.check(vcfRecordGeneInfoMap, variantRecord, pedigree); + if (!isEmpty(compoundsMap)) { + inheritanceResult.setCompounds(compoundsMap); + boolean isCertain = false; + for (Set compoundCheckResult : compoundsMap.values()) { + isCertain = compoundCheckResult.stream().anyMatch(CompoundCheckResult::isCertain); } + Set pedigreeInheritanceMatches = inheritanceResult.getPedigreeInheritanceMatches(); + pedigreeInheritanceMatches.add(new PedigreeInheritanceMatch(AR_C, !isCertain)); + inheritanceResult.setPedigreeInheritanceMatches(pedigreeInheritanceMatches); + inheritanceResult.setCompounds(compoundsMap); + } + } - VariantContext annotatedVc = annotator.annotateInheritance(variantRecord, pedigrees, inheritanceResultMap, probands); - recordWriter.add(annotatedVc); + private boolean isEmpty(Map> compounds) { + for(Set compoundCheckResults : compounds.values()) { + if(!compoundCheckResults.isEmpty()){ + return false; + } } + return true; } - private void addToVcfRecordMap(VariantGeneRecord variantGeneRecord, Map> vcfRecordGeneInfoMap) { - GeneInfo geneInfo = variantGeneRecord.getGeneInfo(); - Set records = vcfRecordGeneInfoMap.containsKey(geneInfo) ? vcfRecordGeneInfoMap.get(geneInfo) : new HashSet<>(); - records.add(variantGeneRecord); - vcfRecordGeneInfoMap.put(geneInfo, records); + private void addToVcfRecordMap(VariantRecord variantRecord, Map> vcfRecordGeneInfoMap) { + for (GeneInfo geneInfo : variantRecord.geneInfos()) { + Set records = vcfRecordGeneInfoMap.containsKey(geneInfo) ? vcfRecordGeneInfoMap.get(geneInfo) : new HashSet<>(); + records.add(variantRecord); + vcfRecordGeneInfoMap.put(geneInfo, records); + } } private Set createFamilyFromVcf(VCFHeader fileHeader) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java index 2d3185a..709681a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java @@ -27,16 +27,16 @@ public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, this.ylChecker = ylChecker; } - MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree pedigree, InheritanceMode mode) { + MatchEnum check(VariantRecord variantRecord, Pedigree pedigree, InheritanceMode mode) { MatchEnum result; switch(mode){ - case AD -> result = adChecker.check(variantGeneRecord, pedigree); - case AD_IP -> result = adNonPenetranceChecker.check(variantGeneRecord, pedigree); - case AR -> result = arChecker.check(variantGeneRecord, pedigree); - case XLR -> result = xlrChecker.check(variantGeneRecord, pedigree); - case XLD -> result = xldChecker.check(variantGeneRecord, pedigree); - case MT -> result = mtChecker.check(variantGeneRecord, pedigree); - case YL -> result = ylChecker.check(variantGeneRecord, pedigree); + case AD -> result = adChecker.check(variantRecord, pedigree); + case AD_IP -> result = adNonPenetranceChecker.check(variantRecord, pedigree); + case AR -> result = arChecker.check(variantRecord, pedigree); + case XLR -> result = xlrChecker.check(variantRecord, pedigree); + case XLD -> result = xldChecker.check(variantRecord, pedigree); + case MT -> result = mtChecker.check(variantRecord, pedigree); + case YL -> result = ylChecker.check(variantRecord, pedigree); default -> throw new UnexpectedEnumException(mode); } return result; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java index 1b4a5ed..38d06dd 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java @@ -11,27 +11,27 @@ public class VariantContextUtils { private VariantContextUtils() { } - public static boolean onAutosome(VariantGeneRecord variantGeneRecord) { + public static boolean onAutosome(VariantRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isAutosome(contigId); } - public static boolean onChromosomeX(VariantGeneRecord variantGeneRecord) { + public static boolean onChromosomeX(VariantRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeX(contigId); } - public static boolean onChromosomeMt(VariantGeneRecord variantGeneRecord) { + public static boolean onChromosomeMt(VariantRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeMt(contigId); } - public static boolean onChromosomeY(VariantGeneRecord variantGeneRecord) { + public static boolean onChromosomeY(VariantRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeY(contigId); } - public static Set getAltAlleles(VariantGeneRecord variantGeneRecord, Pedigree pedigree){ + public static Set getAltAlleles(VariantRecord variantGeneRecord, Pedigree pedigree){ Set altAlleles = new HashSet<>(); for(String sample : pedigree.getMembers().keySet()){ EffectiveGenotype effectiveGenotype = variantGeneRecord.getGenotype(sample); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java deleted file mode 100644 index 65019cf..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantGeneRecord.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.VariantContext; -import lombok.Getter; -import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; - -import java.util.*; - -import static java.util.Objects.requireNonNull; - -public class VariantGeneRecord { - - private final VariantContext variantContext; - @Getter - private final Set pathogenicAlleles; - @Getter - private final GeneInfo geneInfo; - - public VariantGeneRecord(VariantContext variantContext, Set pathogenicAlleles, GeneInfo geneInfo) { - this.variantContext = requireNonNull(variantContext); - this.pathogenicAlleles = requireNonNull(pathogenicAlleles); - this.geneInfo = requireNonNull(geneInfo); - } - - public EffectiveGenotype getGenotype(String sampleId) { - htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); - if (gt == null) { - return null; - } - if(pathogenicAlleles.isEmpty()){ - pathogenicAlleles.addAll(variantContext.getAlternateAlleles()); - } - return new EffectiveGenotype(gt); - } - - public List getAlternateAlleles() { - return variantContext.getAlternateAlleles(); - } - - public VariantContext unwrap() { - return variantContext; - } - - public String getContig() { - return variantContext.getContig(); - } - - public int getStart() { - return variantContext.getStart(); - } - - public Allele getReference() { - return variantContext.getReference(); - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java index 1386d84..031f1e1 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java @@ -1,20 +1,42 @@ package org.molgenis.vcf.inheritance.matcher; -import htsjdk.variant.variantcontext.Genotype; +import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.VariantContext; -import lombok.NonNull; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; -import org.molgenis.vcf.inheritance.matcher.model.InheritanceResult; -import java.util.Map; +import java.util.List; +import java.util.Set; -public record VariantRecord(Map variantGeneRecords, VariantContext variantContext, - InheritanceResult inheritanceResult) { - public Genotype getGenotype(@NonNull String individualId) { - return variantContext.getGenotype(individualId); +public record VariantRecord(VariantContext variantContext, Set pathogenicAlleles, Set geneInfos) { + + public EffectiveGenotype getGenotype(String sampleId) { + htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); + if (gt == null) { + return null; + } + if(pathogenicAlleles.isEmpty()){ + pathogenicAlleles.addAll(variantContext.getAlternateAlleles()); + } + return new EffectiveGenotype(gt); + } + + public List getAlternateAlleles() { + return variantContext.getAlternateAlleles(); + } + + public VariantContext unwrap() { + return variantContext; } public String getContig() { return variantContext.getContig(); } + + public int getStart() { + return variantContext.getStart(); + } + + public Allele getReference() { + return variantContext.getReference(); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java index 66a5256..21f58db 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java @@ -2,7 +2,6 @@ import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.VariantContext; -import org.molgenis.vcf.inheritance.matcher.model.InheritanceResult; import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; @@ -20,12 +19,10 @@ public VcfRecordFactoryImpl(VepMetadata vepMetadata) { @Override public VariantRecord create(VariantContext variantContext, Set pathogenicClasses) { - Map result = new HashMap<>(); - for (GeneInfo geneInfo : getVcfGeneInfos(variantContext)) { - Set pathogenicAlleles = getPathogenicAlleles(variantContext, vepMetadata, pathogenicClasses, geneInfo); - result.put(geneInfo, new VariantGeneRecord(variantContext, pathogenicAlleles, geneInfo)); - } - return new VariantRecord(result, variantContext, InheritanceResult.builder().build()); + Set geneInfos = getVcfGeneInfos(variantContext); + Set pathogenicAlleles = getPathogenicAlleles(variantContext, vepMetadata, pathogenicClasses); + + return new VariantRecord(variantContext, pathogenicAlleles, geneInfos); } private Set getVcfGeneInfos(VariantContext variantContext) { @@ -41,19 +38,19 @@ private Set getVcfGeneInfos(VariantContext variantContext) { return result; } - private Set getPathogenicAlleles(VariantContext variantContext, VepMetadata vepMetadata, Set pathogenicClasses, GeneInfo geneInfo) { + private Set getPathogenicAlleles(VariantContext variantContext, VepMetadata vepMetadata, Set pathogenicClasses) { Set pathogenicAlleles = new HashSet<>(); for (int i = 1; i <= variantContext.getAlternateAlleles().size(); i++) { Allele allele = variantContext.getAlleles().get(i); - if (isAllelePathogenic(variantContext, vepMetadata, i, geneInfo, pathogenicClasses)) { + if (isAllelePathogenic(variantContext, vepMetadata, i, pathogenicClasses)) { pathogenicAlleles.add(allele); } } return pathogenicAlleles; } - public boolean isAllelePathogenic(VariantContext variantContext, VepMetadata vepMetadata, int alleleIndex, GeneInfo geneInfo, Set pathogenicClasses) { + public boolean isAllelePathogenic(VariantContext variantContext, VepMetadata vepMetadata, int alleleIndex, Set pathogenicClasses) { if (pathogenicClasses.isEmpty()) { return true; } @@ -65,7 +62,7 @@ public boolean isAllelePathogenic(VariantContext variantContext, VepMetadata vep for (String vepValue : vepValues) { String[] vepSplit = vepValue.split("\\|", -1); int csqAlleleIndex = Integer.parseInt(vepSplit[vepMetadata.getAlleleNumIndex()]); - if (csqAlleleIndex == alleleIndex && geneInfo.geneId().equals(vepSplit[vepMetadata.getGeneIndex()])) { + if (csqAlleleIndex == alleleIndex) { result = pathogenicClasses.contains(vepSplit[vepMetadata.getClassIndex()]); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java index 02b20c6..e6e4d27 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java @@ -53,14 +53,18 @@ private void init() { FieldMetadata fieldMetadata = fieldMetadataService.load( vcfInfoHeaderLine); Map nestedFields = fieldMetadata.getNestedFields(); - geneIndex = nestedFields.get(GENE) != null ? nestedFields.get(GENE).getIndex():-1; - geneSourceIndex = nestedFields.get(SYMBOL_SOURCE) != null ? nestedFields.get(SYMBOL_SOURCE).getIndex():-1; - inheritanceIndex = nestedFields.get(INHERITANCE) != null ? nestedFields.get(INHERITANCE).getIndex():-1; - alleleNumIndex = nestedFields.get(ALLELE_NUM) != null ? nestedFields.get(ALLELE_NUM).getIndex():-1; - classIndex = nestedFields.get(VIP_CLASS) != null ? nestedFields.get(VIP_CLASS).getIndex():-1; + geneIndex = getIndex(nestedFields, GENE); + geneSourceIndex = getIndex(nestedFields, SYMBOL_SOURCE); + inheritanceIndex = getIndex(nestedFields, INHERITANCE); + alleleNumIndex = getIndex(nestedFields, ALLELE_NUM); + classIndex = getIndex(nestedFields, VIP_CLASS); return; } } throw new MissingInfoException("VEP"); } + + private static int getIndex(Map nestedFields, String fieldName) { + return nestedFields.get(fieldName) != null ? nestedFields.get(fieldName).getIndex() : -1; + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index f623d0d..d1cec83 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -2,7 +2,7 @@ import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -23,18 +23,18 @@ public class AdChecker extends DominantChecker { * Check whether the AD inheritance pattern could match for a variant in a pedigree */ public MatchEnum check( - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantGeneRecord)) { + VariantRecord variantRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantRecord)) { return FALSE; } - return checkFamily(variantGeneRecord, family); + return checkFamily(variantRecord, family); } - public MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if(genotype == null){ matches.add(POTENTIAL); } @@ -48,14 +48,14 @@ else if(genotype.isHomRef()){ return merge(matches); } - public MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); - if (genotype.isHomRef()) { + if (genotype != null && genotype.isHomRef()) { return FALSE; - } else if ((genotype.hasMissingAllele() && genotype.hasReference()) || genotype.isNoCall()) { + } else if (genotype == null || (genotype.hasMissingAllele() && genotype.hasReference()) || genotype.isNoCall()) { matches.add(POTENTIAL); } else { matches.add(TRUE); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java index 58b427a..88538c0 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java @@ -4,7 +4,7 @@ import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -17,28 +17,28 @@ public class AdNonPenetranceChecker { public MatchEnum check( - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantGeneRecord)) { + VariantRecord variantRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantRecord)) { return FALSE; } Set results = new HashSet<>(); for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, variantGeneRecord)); + results.add(checkSample(sample, variantRecord)); } return CheckerUtils.merge(results); } - MatchEnum checkSample(Sample sample, VariantGeneRecord variantGeneRecord) { - EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(sample.getPerson().getIndividualId()); + MatchEnum checkSample(Sample sample, VariantRecord variantRecord) { + EffectiveGenotype sampleGt = variantRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { - if (sampleGt.isHomRef()) { + if (sampleGt != null && sampleGt.isHomRef()) { return FALSE; - } else if (sampleGt.isMixed()) { - return sampleGt.hasAlt() ? TRUE : POTENTIAL; + } else if (sampleGt != null && sampleGt.isMixed()) { + return sampleGt.hasAltAllele() ? TRUE : POTENTIAL; } else { - return TRUE; + return sampleGt == null ? POTENTIAL : TRUE; } } case UNAFFECTED -> { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java index b07b0c5..ed7b856 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java @@ -6,7 +6,7 @@ import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -19,18 +19,18 @@ public class ArChecker extends InheritanceChecker { public MatchEnum check( - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantGeneRecord)) { + VariantRecord variantRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(variantRecord)) { return FALSE; } - return checkFamily(variantGeneRecord, family); + return checkFamily(variantRecord, family); } - protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if(genotype == null){ matches.add(POTENTIAL); } else if (genotype.hasReference()) { @@ -45,14 +45,14 @@ protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); - if (genotype.hasReference()) { + if (genotype!= null && genotype.hasReference()) { return FALSE; - } else if ((genotype.isMixed()) || genotype.isNoCall()) { + } else if (genotype == null || genotype.isMixed() || genotype.isNoCall()) { matches.add(POTENTIAL); } else { matches.add(TRUE); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index d31b32e..9f9de41 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -10,7 +10,7 @@ import java.util.*; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -20,24 +20,27 @@ public class ArCompoundChecker { - public Set check( - Map> geneVariantMap, - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (onAutosome(variantGeneRecord)) { - Set compounds = new HashSet<>(); - checkForGene(geneVariantMap, variantGeneRecord, family, compounds); + public Map> check( + Map> geneVariantMap, + VariantRecord variantRecord, Pedigree family) { + if (onAutosome(variantRecord)) { + Map> compounds = new HashMap<>(); + for (GeneInfo geneInfo : variantRecord.geneInfos()) { + checkForGene(geneVariantMap, variantRecord, family, compounds, geneInfo); + } return compounds; } - return Collections.emptySet(); + return Collections.emptyMap(); } - private void checkForGene(Map> geneVariantMap, - VariantGeneRecord variantGeneRecord, Pedigree family, Set compounds) { - Collection variantGeneRecords = geneVariantMap.get(variantGeneRecord.getGeneInfo()); + private void checkForGene(Map> geneVariantMap, + VariantRecord variantRecord, Pedigree family, Map> compoundsMap, GeneInfo geneInfo) { + Collection variantGeneRecords = geneVariantMap.get(geneInfo); + Set compounds = new HashSet<>(); if (variantGeneRecords != null) { - for (VariantGeneRecord otherRecord : variantGeneRecords) { - if (!otherRecord.equals(variantGeneRecord)) { - MatchEnum isPossibleCompound = checkFamily(family, variantGeneRecord, otherRecord); + for (VariantRecord otherRecord : variantGeneRecords) { + if (!otherRecord.equals(variantRecord)) { + MatchEnum isPossibleCompound = checkFamily(family, variantRecord, otherRecord); if (isPossibleCompound != FALSE) { CompoundCheckResult result = CompoundCheckResult.builder().possibleCompound(otherRecord).isCertain(isPossibleCompound != POTENTIAL).build(); compounds.add(result); @@ -45,91 +48,100 @@ private void checkForGene(Map> geneVariantMap, } } } + compoundsMap.put(geneInfo, compounds); } - private MatchEnum checkFamily(Pedigree family, VariantGeneRecord variantGeneRecord, - VariantGeneRecord otherVariantGeneRecord) { + private MatchEnum checkFamily(Pedigree family, VariantRecord variantRecord, + VariantRecord otherVariantGeneRecord) { Map> membersByStatus = getMembersByStatus(family); Set> affectedGenotypes = new HashSet<>(); Set> otherAffectedGenotypes = new HashSet<>(); Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); - matches.add(checkUnaffected(variantGeneRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); - if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ + matches.add(checkAffected(variantRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); + matches.add(checkUnaffected(variantRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); + if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { matches.add(POTENTIAL); } return merge(matches); } - private MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, VariantGeneRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { + private MatchEnum checkUnaffected(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - matches.add(checkUnaffectedSample(variantGeneRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, unAffectedSample)); + matches.add(checkUnaffectedSample(variantRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, unAffectedSample)); } return merge(matches); } - private static MatchEnum checkUnaffectedSample(VariantGeneRecord variantGeneRecord, VariantGeneRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample unAffectedSample) { + private static MatchEnum checkUnaffectedSample(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample unAffectedSample) { Set matches = new HashSet<>(); - matches.add(checkSingleUnaffectedSampleVariant(variantGeneRecord, affectedGenotypes, unAffectedSample)); + matches.add(checkSingleUnaffectedSampleVariant(variantRecord, affectedGenotypes, unAffectedSample)); matches.add(checkSingleUnaffectedSampleVariant(otherVariantGeneRecord, otherAffectedGenotypes, unAffectedSample)); - if(matches.contains(TRUE)){ + if (matches.contains(TRUE)) { return TRUE; } else if (matches.contains(POTENTIAL)) { return POTENTIAL; } - EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype sampleGt = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); - if(sampleGt.isPhased() && sampleOtherGt.isPhased() && + + if ((sampleGt != null && sampleOtherGt != null) && (sampleGt.isPhased() && sampleOtherGt.isPhased() && (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || - (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference())){ + (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference()))) { return TRUE; } return FALSE; } - private static MatchEnum checkSingleUnaffectedSampleVariant(VariantGeneRecord variantGeneRecord, Set> affectedGenotypes, Sample unAffectedSample) { + private static MatchEnum checkSingleUnaffectedSampleVariant(VariantRecord variantRecord, Set> affectedGenotypes, Sample unAffectedSample) { Set matches = new HashSet<>(); - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); for (List affectedGenotype : affectedGenotypes) { - if(genotype != null && genotype.isHomRef()){ + if (genotype != null && genotype.isHomRef()) { matches.add(TRUE); - } - else if (affectedGenotype.stream().filter(Allele::isNonReference).allMatch( - allele -> allele.isCalled() && genotype!= null && genotype.getAlleles().contains(allele))) { + } else if (affectedGenotype.stream().filter(Allele::isNonReference).allMatch( + allele -> allele.isCalled() && genotype != null && genotype.getAlleles().contains(allele))) { matches.add(FALSE); - } else{ + } else { matches.add(POTENTIAL); } } return merge(matches); } - private MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, VariantGeneRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { + private MatchEnum checkAffected(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype sampleGt = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); - EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); - if(sampleGt != null) { - affectedGenotypes.add(sampleGt.getAlleles()); - } - if(sampleOtherGt != null) { - otherAffectedGenotypes.add(sampleOtherGt.getAlleles()); - } - if((sampleGt != null && sampleGt.isHom()) || (sampleOtherGt != null && sampleOtherGt.isHom())){ - return FALSE; - } else if ((sampleGt == null || !sampleGt.hasReference()) || (sampleOtherGt == null || !sampleOtherGt.hasReference())) { - matches.add(POTENTIAL); - } else{ - if(sampleGt.isPhased() && sampleOtherGt.isPhased() && - (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || - (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference())){ - return FALSE; - } - matches.add(TRUE); - } + checkAffectedSample(variantRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, affectedSample, matches); } return merge(matches); } + + private static void checkAffectedSample(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample affectedSample, Set matches) { + EffectiveGenotype sampleGt = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + if (sampleGt != null) { + affectedGenotypes.add(sampleGt.getAlleles()); + } + if (sampleOtherGt != null) { + otherAffectedGenotypes.add(sampleOtherGt.getAlleles()); + } + if ((sampleGt != null && sampleGt.isHom()) || (sampleOtherGt != null && sampleOtherGt.isHom())) { + matches.add(FALSE); + } else if ((sampleGt == null || !sampleGt.hasReference()) || (sampleOtherGt == null || !sampleOtherGt.hasReference())) { + matches.add(POTENTIAL); + } else { + if (checkAffectedPhased(sampleGt, sampleOtherGt)) { + matches.add(FALSE); + } + matches.add(TRUE); + } + } + + private static boolean checkAffectedPhased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { + return sampleGt.isPhased() && sampleOtherGt.isPhased() && + (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || + (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference()); + } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java index b65d565..6826885 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/CheckerUtils.java @@ -11,7 +11,7 @@ public class CheckerUtils { - private CheckerUtils(){}; + private CheckerUtils(){} public static Map> getMembersByStatus(Pedigree family) { Map> membersByStatus = new EnumMap<>(AffectedStatus.class); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java index e759780..622d98e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java @@ -3,8 +3,8 @@ import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.*; -import htsjdk.variant.variantcontext.Genotype; import org.molgenis.vcf.inheritance.matcher.ContigUtils; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; @@ -16,9 +16,9 @@ public class DeNovoChecker { //use original GT instead of inheritance matcher specific one since we are looking for "new alleles" not specifically pathogenic ones public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { - Genotype probandGt = variantRecord.getGenotype(proband.getPerson().getIndividualId()); - Genotype fatherGt = variantRecord.getGenotype(proband.getPerson().getPaternalId()); - Genotype motherGt = variantRecord.getGenotype(proband.getPerson().getMaternalId()); + EffectiveGenotype probandGt = variantRecord.getGenotype(proband.getPerson().getIndividualId()); + EffectiveGenotype fatherGt = variantRecord.getGenotype(proband.getPerson().getPaternalId()); + EffectiveGenotype motherGt = variantRecord.getGenotype(proband.getPerson().getMaternalId()); if (!hasParents(proband)) { return POTENTIAL; @@ -26,16 +26,7 @@ public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { String contigId = variantRecord.getContig(); if ((contigId != null && ContigUtils.isChromosomeX(contigId)) && proband.getPerson().getSex() == Sex.MALE) { - if (probandGt.hasAltAllele()) { - if (motherGt.hasAltAllele()) { - return FALSE; - } else if (motherGt.isHomRef()) { - return TRUE; - } else { - return POTENTIAL; - } - } - return probandGt.isNoCall() ? POTENTIAL : FALSE; + return checkMaleXVariant(probandGt, motherGt); } else if ((contigId != null && ContigUtils.isChromosomeY(contigId))) { return checkYLinkedVariant(proband, probandGt, fatherGt); } else if ((contigId != null && ContigUtils.isChromosomeMt(contigId))) { @@ -45,7 +36,22 @@ public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { } } - private static MatchEnum checkYLinkedVariant(Sample proband, Genotype probandGt, Genotype fatherGt) { + private static MatchEnum checkMaleXVariant(EffectiveGenotype probandGt, EffectiveGenotype motherGt) { + if(probandGt == null){ + return POTENTIAL; + } else if (probandGt.hasAltAllele()) { + if (motherGt != null && motherGt.hasAltAllele()) { + return FALSE; + } else if (motherGt != null && motherGt.isHomRef()) { + return TRUE; + } else { + return POTENTIAL; + } + } + return probandGt.isNoCall() ? POTENTIAL : FALSE; + } + + private static MatchEnum checkYLinkedVariant(Sample proband, EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { return switch (proband.getPerson().getSex()) { case MALE -> checkYLinkedVariantMale(probandGt, fatherGt); case FEMALE -> FALSE; @@ -53,7 +59,7 @@ private static MatchEnum checkYLinkedVariant(Sample proband, Genotype probandGt, }; } - private static MatchEnum checkYLinkedVariantMale(Genotype probandGt, Genotype fatherGt) { + private static MatchEnum checkYLinkedVariantMale(EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { if (probandGt.hasAltAllele()) { if (fatherGt.hasAltAllele()) { return FALSE; @@ -66,11 +72,13 @@ private static MatchEnum checkYLinkedVariantMale(Genotype probandGt, Genotype fa return FALSE; } - private static MatchEnum checkMtVariant(Genotype probandGt, Genotype motherGt) { - if (probandGt.hasAltAllele()) { - if (motherGt.hasAltAllele()) { + private static MatchEnum checkMtVariant(EffectiveGenotype probandGt, EffectiveGenotype motherGt) { + if (probandGt == null) { + return POTENTIAL; + }else if (probandGt.hasAltAllele()) { + if (motherGt != null && motherGt.hasAltAllele()) { return FALSE; - } else if (!motherGt.hasAltAllele() && motherGt.isCalled() && !motherGt.isMixed()) { + } else if (motherGt != null && !motherGt.hasAltAllele() && motherGt.isCalled() && !motherGt.isMixed()) { return TRUE; } else { return POTENTIAL; @@ -85,7 +93,7 @@ private static MatchEnum checkMtVariant(Genotype probandGt, Genotype motherGt) { return FALSE; } - private MatchEnum checkRegular(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { + private MatchEnum checkRegular(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { MatchEnum result = FALSE; if (probandGt != null) { if (probandGt.isHom()) { @@ -101,7 +109,7 @@ private MatchEnum checkRegular(Genotype probandGt, Genotype fatherGt, Genotype m return result; } - private static MatchEnum checkMixed(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { + private static MatchEnum checkMixed(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { MatchEnum result; if (probandGt.hasAltAllele()) { if (motherGt.isHomRef() && fatherGt.isHomRef()) { @@ -121,7 +129,7 @@ private static MatchEnum checkMixed(Genotype probandGt, Genotype fatherGt, Genot return result; } - private static MatchEnum checkHetrozygote(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { + private static MatchEnum checkHetrozygote(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { if (probandGt.hasAltAllele()) { if (motherGt.isHomRef() && fatherGt.isHomRef()) { return TRUE; @@ -134,7 +142,7 @@ private static MatchEnum checkHetrozygote(Genotype probandGt, Genotype fatherGt, return FALSE; } - private static MatchEnum checkHomozygote(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { + private static MatchEnum checkHomozygote(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { if (probandGt.hasAltAllele()) { if (motherGt.isHomRef() || fatherGt.isHomRef()) { return TRUE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java index 2ec6b19..0def21b 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -17,12 +17,12 @@ public abstract class DominantChecker { - MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + MatchEnum checkFamily(VariantRecord variantRecord, Pedigree family) { Map> membersByStatus = getMembersByStatus(family); Set affectedGenotypes = new HashSet<>(); Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + matches.add(checkAffected(variantRecord, membersByStatus, affectedGenotypes)); + matches.add(checkUnaffected(variantRecord, membersByStatus, affectedGenotypes)); if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ matches.add(POTENTIAL); } @@ -31,7 +31,7 @@ MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { static void checkAffectedGenotypes(Set affectedGenotypes, Set matches, EffectiveGenotype genotype) { for (EffectiveGenotype affectedGenotype : affectedGenotypes) { - if (affectedGenotype.hasAlt() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( + if (affectedGenotype.hasAltAllele() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( allele -> genotype.getAlleles().contains(allele))) { matches.add(FALSE); } else { @@ -40,7 +40,7 @@ static void checkAffectedGenotypes(Set affectedGenotypes, Set } } - protected abstract MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes); - protected abstract MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java index 2e26122..d5c0362 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java @@ -2,7 +2,7 @@ import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -18,21 +18,21 @@ public abstract class InheritanceChecker { - protected MatchEnum checkFamily(VariantGeneRecord variantGeneRecord, Pedigree family) { + protected MatchEnum checkFamily(VariantRecord variantRecord, Pedigree family) { Map> membersByStatus = getMembersByStatus(family); Set affectedGenotypes = new HashSet<>(); Set matches = new HashSet<>(); - matches.add(checkAffected(variantGeneRecord, membersByStatus, affectedGenotypes)); + matches.add(checkAffected(variantRecord, membersByStatus, affectedGenotypes)); Set affectedAltAlleles = new HashSet<>(); affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); - matches.add(checkUnaffected(variantGeneRecord, membersByStatus, affectedAltAlleles)); + matches.add(checkUnaffected(variantRecord, membersByStatus, affectedAltAlleles)); if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { matches.add(POTENTIAL); } return merge(matches); } - protected abstract MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes); - protected abstract MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAltAlleles); + protected abstract MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAltAlleles); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java index 41f05ea..510ba8c 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java @@ -3,7 +3,7 @@ import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -20,18 +20,18 @@ @Component public class MtChecker extends InheritanceChecker { public MatchEnum check( - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!VariantContextUtils.onChromosomeMt(variantGeneRecord)) { + VariantRecord variantRecord, Pedigree family) { + if (!VariantContextUtils.onChromosomeMt(variantRecord)) { return FALSE; } - return checkFamily(variantGeneRecord, family); + return checkFamily(variantRecord, family); } - protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if (genotype != null && (genotype.isHomRef() || (genotype.getPloidy() == 1 && genotype.hasReference()))) { matches.add(TRUE); } else if (genotype != null && genotype.getAlleles().stream().allMatch( @@ -45,14 +45,14 @@ protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); - if (!genotype.hasAlt() && genotype.isCalled()) { + if (genotype != null && !genotype.hasAltAllele() && genotype.isCalled()) { return FALSE; - } else if (genotype.isNoCall() || (genotype.isMixed())) { + } else if (genotype == null || genotype.isNoCall() || (genotype.isMixed())) { matches.add(POTENTIAL); } else { matches.add(TRUE); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index 3bfd2f4..b2e7334 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -17,21 +17,21 @@ @Component public class XldChecker extends DominantChecker { - public MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!onChromosomeX(variantGeneRecord)) { + public MatchEnum check(VariantRecord variantRecord, Pedigree family) { + if (!onChromosomeX(variantRecord)) { return FALSE; } - return checkFamily(variantGeneRecord, family); + return checkFamily(variantRecord, family); } - public MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if(genotype == null){ matches.add(POTENTIAL); } - else if(!genotype.hasAlt() && !genotype.isMixed() || (genotype.hasReference() && genotype.getPloidy() == 2)){ + else if(!genotype.hasAltAllele() && !genotype.isMixed() || (genotype.hasReference() && genotype.getPloidy() == 2)){ matches.add(TRUE); } else { @@ -41,14 +41,14 @@ else if(!genotype.hasAlt() && !genotype.isMixed() || (genotype.hasReference() && return merge(matches); } - public MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); - if (!genotype.hasAlt() && !genotype.isMixed()) { + if (genotype != null && !genotype.hasAltAllele() && !genotype.isMixed()) { return FALSE; - } else if ((genotype.hasMissingAllele() && genotype.hasReference()) || genotype.isNoCall()) { + } else if (genotype == null || (genotype.hasMissingAllele() && genotype.hasReference()) || genotype.isNoCall()) { matches.add(POTENTIAL); } else { matches.add(TRUE); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index 7d13712..a25e277 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -2,7 +2,7 @@ import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -18,17 +18,17 @@ @Component public class XlrChecker extends InheritanceChecker { - public MatchEnum check(VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!onChromosomeX(variantGeneRecord)) { + public MatchEnum check(VariantRecord variantRecord, Pedigree family) { + if (!onChromosomeX(variantRecord)) { return FALSE; } - return checkFamily(variantGeneRecord, family); + return checkFamily(variantRecord, family); } - protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if (genotype != null && genotype.hasReference()) { matches.add(TRUE); } else if (genotype != null && genotype.getAlleles().stream().allMatch( @@ -41,14 +41,14 @@ protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); - if (genotype.hasReference()) { + if (genotype != null && genotype.hasReference()) { return FALSE; - } else if ((genotype.hasMissingAllele()) || genotype.isNoCall()) { + } else if ((genotype == null || genotype.hasMissingAllele()) || genotype.isNoCall()) { matches.add(POTENTIAL); } else { matches.add(TRUE); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java index d6360a7..e92a866 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java @@ -3,12 +3,11 @@ import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; -import org.molgenis.vcf.utils.sample.model.Sex; import org.springframework.stereotype.Component; import java.util.HashSet; @@ -23,46 +22,47 @@ @Component public class YlChecker extends InheritanceChecker { public MatchEnum check( - VariantGeneRecord variantGeneRecord, Pedigree family) { - if (!VariantContextUtils.onChromosomeY(variantGeneRecord)) { + VariantRecord variantRecord, Pedigree family) { + if (!VariantContextUtils.onChromosomeY(variantRecord)) { return FALSE; } - return checkFamily(variantGeneRecord, family); + return checkFamily(variantRecord, family); } - protected MatchEnum checkUnaffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); - if(getSex(unAffectedSample, genotype) == FEMALE){ + EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + if (unAffectedSample.getPerson().getSex() != MALE) { matches.add(TRUE); + } else if (genotype == null) { + matches.add(POTENTIAL); } else if (genotype.isHomRef() || (genotype.getPloidy() == 1 && genotype.hasReference())) { matches.add(TRUE); - } - else { - if (genotype.getAlleles().stream().allMatch( - allele -> allele.isCalled() && affectedAlleles.contains(allele))) { - matches.add(FALSE); - } else { - matches.add(POTENTIAL); - } + } else { + if (genotype.getAlleles().stream().allMatch( + allele -> allele.isCalled() && affectedAlleles.contains(allele))) { + matches.add(FALSE); + } else { + matches.add(POTENTIAL); + } } } return merge(matches); } - protected MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); - if(getSex(affectedSample, genotype) == FEMALE){ + EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + if (affectedSample.getPerson().getSex() == FEMALE) { return FALSE; } affectedGenotypes.add(genotype); - if (!genotype.hasAlt() && genotype.isCalled()) { + if (genotype != null && !genotype.hasAltAllele() && genotype.isCalled()) { return FALSE; - } else if (genotype.isNoCall() || (genotype.isMixed())) { + } else if (genotype == null || genotype.isNoCall() || genotype.isMixed() || genotype.isHet()) { matches.add(POTENTIAL); } else { matches.add(TRUE); @@ -70,18 +70,4 @@ protected MatchEnum checkAffected(VariantGeneRecord variantGeneRecord, Map { - - @NonNull - GeneInfo geneInfo; - @Builder.Default - Set pedigreeInheritanceMatches = new HashSet<>(); - @Builder.Default - Set compounds = new HashSet<>(); - - public void addInheritanceMode(PedigreeInheritanceMatch pedigreeInheritanceMatch) { - pedigreeInheritanceMatches.add(pedigreeInheritanceMatch); - } - - /** - * If there is a match between sample inheritance modes and gene inheritance modes: - * - inheritance match is true - * If there are no matches between sample inheritance modes and gene inheritance modes: - * - inheritance match is unknown ifa gene has unknown inheritance pattern. - * - inheritance match is false if a gene has known (but mismatching) inheritance pattern. - */ - public MatchEnum getMatch() { - //If no inheritance pattern is suitable for the sample, regardless of the gene: inheritance match is false. - if(pedigreeInheritanceMatches.isEmpty()){ - return FALSE; - } - boolean containsUnknownGene = false; - - Set geneInheritanceModes = geneInfo - .inheritanceModes(); - if( geneInheritanceModes.isEmpty() ){ - containsUnknownGene = true; - } - if (geneInheritanceModes.stream() - .anyMatch(geneInheritanceMode -> isMatch(pedigreeInheritanceMatches, geneInheritanceMode))) { - if(pedigreeInheritanceMatches.stream().anyMatch(pedigreeInheritanceMatch -> !pedigreeInheritanceMatch.isUncertain())){ - return TRUE; - }else { - return POTENTIAL; - } - } - return containsUnknownGene? POTENTIAL : FALSE; - } - private static Boolean isMatch(Set pedigreeInheritanceMatches, InheritanceMode geneInheritanceMode) { - for(PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { - switch (pedigreeInheritanceMatch.inheritanceMode()) { - case AD, AD_IP -> { - if (geneInheritanceMode == AD) { - return true; - } - } - case AR, AR_C -> { - if (geneInheritanceMode == AR) { - return true; - } - } - case XLR, XLD -> { - if (geneInheritanceMode == XL) { - return true; - } - } - case YL -> { - if (geneInheritanceMode == YL) { - return true; - } - } - case MT -> { - if (geneInheritanceMode == MT) { - return true; - } - } - default -> throw new UnexpectedEnumException(pedigreeInheritanceMatch.inheritanceMode()); - } - } - return false; - } - - @Override - public int compareTo(InheritanceGeneResult o) { - return geneInfo.compareTo(o.getGeneInfo()); - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java index 9a7ce60..a5fd10b 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/InheritanceResult.java @@ -11,6 +11,13 @@ public class InheritanceResult { @Builder.Default - Collection inheritanceGeneResults = new HashSet<>(); + Set pedigreeInheritanceMatches = new HashSet<>(); + @Builder.Default + Map> compounds = new HashMap<>(); + + public void addInheritanceMode(PedigreeInheritanceMatch pedigreeInheritanceMatch) { + pedigreeInheritanceMatches.add(pedigreeInheritanceMatch); + } + Map denovo; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java index e95e20a..eac3e9a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.util; import htsjdk.variant.variantcontext.Allele; -import htsjdk.variant.variantcontext.Genotype; +import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.utils.sample.model.Sample; public class InheritanceUtils { @@ -13,7 +13,7 @@ public static boolean hasParents(Sample sample) { !(sample.getPerson().getPaternalId().isEmpty() || sample.getPerson().getPaternalId().equals("0")); } - public static boolean hasMissing(Genotype genotype) { + public static boolean hasMissing(EffectiveGenotype genotype) { return genotype == null || genotype.getAlleles().stream() .anyMatch(Allele::isNoCall); } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java index d273db5..dfe4a16 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java @@ -46,70 +46,70 @@ void setUp() { @Test void testAdPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(adChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.AD); + when(adChecker.check(variantRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.AD); assertEquals(POTENTIAL, actual); } @Test void testAdIpTrue() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(adNonPenetranceChecker.check(variantGeneRecord, family)).thenReturn(TRUE); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.AD_IP); + when(adNonPenetranceChecker.check(variantRecord, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.AD_IP); assertEquals(TRUE, actual); } @Test void testArPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(arChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.AR); + when(arChecker.check(variantRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.AR); assertEquals(POTENTIAL, actual); } @Test void testXldFalse() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(xldChecker.check(variantGeneRecord, family)).thenReturn(FALSE); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.XLD); + when(xldChecker.check(variantRecord, family)).thenReturn(FALSE); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.XLD); assertEquals(FALSE, actual); } @Test void testXlrPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(xlrChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.XLR); + when(xlrChecker.check(variantRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.XLR); assertEquals(POTENTIAL, actual); } @Test void testYlTrue() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(ylChecker.check(variantGeneRecord, family)).thenReturn(TRUE); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.YL); + when(ylChecker.check(variantRecord, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.YL); assertEquals(TRUE, actual); } @Test void testMtPotential() { VariantContext vc = mock(VariantContext.class); - VariantGeneRecord variantGeneRecord = new VariantGeneRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), new GeneInfo("","",Set.of(InheritanceMode.AD_IP))); + VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(mtChecker.check(variantGeneRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantGeneRecord, family, InheritanceMode.MT); + when(mtChecker.check(variantRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.MT); assertEquals(POTENTIAL, actual); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java index 69cc48c..e28c86a 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java @@ -13,7 +13,7 @@ class VariantContextUtilsTest { @Mock - private VariantGeneRecord variantContext; + private VariantRecord variantContext; @Test void onAutosomeTrue() { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java index fa8b5b0..6aa2e0c 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,10 +31,10 @@ class AdCheckerTest { final AdChecker adChecker = new AdChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adChecker.check(variantGeneRecord, family)); + assertEquals(expected, adChecker.check(variantRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java index 0d32a4e..23020a2 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java @@ -1,5 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; +import static htsjdk.variant.variantcontext.Allele.*; import static java.util.Collections.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; @@ -14,6 +15,7 @@ import java.nio.file.Files; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.stream.Stream; import org.junit.jupiter.api.Test; @@ -22,7 +24,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; @@ -37,17 +39,18 @@ class AdNonPenCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adNonPenetranceChecker.check(variantGeneRecord, family)); + assertEquals(expected, adNonPenetranceChecker.check(variantRecord, family)); } @Test void testCheckAd() { VariantContext variantContext = mock(VariantContext.class); Pedigree family = mock(Pedigree.class); - assertEquals(FALSE, adNonPenetranceChecker.check(new VariantGeneRecord(variantContext, emptySet(), new GeneInfo("TEST", "SOURCE", emptySet())), family)); + + assertEquals(FALSE, adNonPenetranceChecker.check(new VariantRecord(variantContext, Set.of(ALT_A,ALT_G,ALT_N), Set.of(new GeneInfo("GENE1", "SOURCE", emptySet()))), family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java index 1672a14..7332199 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,10 +31,10 @@ class ArCheckerTest { final ArChecker arChecker = new ArChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, arChecker.check(variantGeneRecord, family)); + assertEquals(expected, arChecker.check(variantRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java index f47d5a7..f84180d 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java @@ -23,7 +23,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -36,21 +36,41 @@ class ArCompoundCheckerTest { @ParameterizedTest(name = "{index} {4}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Map> geneVariantMap, + void check(VariantRecord variantRecord, Map> geneVariantMap, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); ArCompoundChecker arCompoundChecker = new ArCompoundChecker(); - Set compounds = arCompoundChecker.check(geneVariantMap, variantGeneRecord, family); + Map> compounds = arCompoundChecker.check(geneVariantMap, variantRecord, family); if (expected == FALSE) { - assertTrue(compounds.isEmpty()); + assertTrue(isEmpty(compounds)); } else if (expected == TRUE) { - assertTrue(compounds.stream().anyMatch(CompoundCheckResult::isCertain)); + assertTrue(!isEmpty(compounds) && containsCertainMatch(compounds)); } else { - assertTrue(!compounds.isEmpty() && compounds.stream().noneMatch(CompoundCheckResult::isCertain)); + assertTrue(!isEmpty(compounds) && !containsCertainMatch(compounds)); } } + private boolean isEmpty(Map> compounds) { + for(Set compoundCheckResults : compounds.values()) { + if(!compoundCheckResults.isEmpty()){ + return false; + } + } + return true; + } + + private boolean containsCertainMatch(Map> compounds) { + for(Set compoundCheckResults : compounds.values()) { + for(CompoundCheckResult compoundCheckResult : compoundCheckResults) { + if(compoundCheckResult.isCertain()) { + return true; + } + } + } + return false; + } + private static Stream provideTestCases() throws IOException { File testFile = ResourceUtils.getFile("classpath:ArCompoundTests.tsv"); List lines = Files.lines(testFile.toPath()) diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java index a4225e3..83c0b1b 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java @@ -9,14 +9,12 @@ import java.nio.file.Files; import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.stream.Stream; + import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; import org.molgenis.vcf.inheritance.matcher.VariantRecord; -import org.molgenis.vcf.inheritance.matcher.model.InheritanceResult; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -37,30 +35,29 @@ void check(VariantRecord variantRecord, Pedigree family, String expectedString, assertEquals(expected, deNovoChecker.checkDeNovo(variantRecord, individual)); } - private static Stream provideTestCases() throws IOException { - File testFile = ResourceUtils.getFile("classpath:DenovoTests.tsv"); - List lines = Files.lines(testFile.toPath()) - .map(line -> line.split("\t")).toList(); - - return lines.stream().skip(1).map(line -> { - String testName = line[0]; - String probandGt = line[1]; - Sex probandSex = Sex.valueOf(line[2]); - String fatherGt = line[3]; - String motherGt = line[4]; - String chrom = line[5]; - String expected = line[6]; - - Pedigree family = PedigreeTestUtil - .createFamily(probandSex, AffectedStatus.MISSING, AffectedStatus.MISSING, - AffectedStatus.MISSING, "FAM001"); - VariantGeneRecord variantGeneRecord = VariantContextTestUtil - .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), - createGenotype("Father", fatherGt), - createGenotype("Mother", motherGt)), "", chrom); - - return Arguments.of(new VariantRecord(Map.of(variantGeneRecord.getGeneInfo(), variantGeneRecord), variantGeneRecord.unwrap(),InheritanceResult.builder().build()), family, expected, testName); - - }); - } + private static Stream provideTestCases() throws IOException { + File testFile = ResourceUtils.getFile("classpath:DenovoTests.tsv"); + List lines = Files.lines(testFile.toPath()) + .map(line -> line.split("\t")).toList(); + + return lines.stream().skip(1).map(line -> { + String testName = line[0]; + String probandGt = line[1]; + Sex probandSex = Sex.valueOf(line[2]); + String fatherGt = line[3]; + String motherGt = line[4]; + String chrom = line[5]; + String expected = line[6]; + + Pedigree family = PedigreeTestUtil + .createFamily(probandSex, AffectedStatus.MISSING, AffectedStatus.MISSING, + AffectedStatus.MISSING, "FAM001"); + VariantRecord variantRecord = VariantContextTestUtil + .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), + createGenotype("Father", fatherGt), + createGenotype("Mother", motherGt)), "", chrom); + + return Arguments.of(variantRecord, family, expected, testName); + }); + } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java index b0699b4..530f80f 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -32,10 +32,10 @@ class MtCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, mtChecker.check(variantGeneRecord, family)); + assertEquals(expected, mtChecker.check(variantRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java index d46e567..907e4f3 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -29,10 +29,10 @@ class XldCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xldChecker.check(variantGeneRecord, family)); + assertEquals(expected, xldChecker.check(variantRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java index 8572e7d..9b9e3cd 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -29,10 +29,10 @@ class XlrCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xlrChecker.check(variantGeneRecord, family)); + assertEquals(expected, xlrChecker.check(variantRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java index a8abf4f..f6bd757 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -32,10 +32,10 @@ class YlCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantGeneRecord variantGeneRecord, Pedigree family, String expectedString, + void check(VariantRecord variantRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, ylChecker.check(variantGeneRecord, family)); + assertEquals(expected, ylChecker.check(variantRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java index 4564719..4edd6a8 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java @@ -4,7 +4,7 @@ import htsjdk.variant.variantcontext.Genotype; import htsjdk.variant.variantcontext.GenotypeBuilder; import htsjdk.variant.variantcontext.VariantContextBuilder; -import org.molgenis.vcf.inheritance.matcher.VariantGeneRecord; +import org.molgenis.vcf.inheritance.matcher.VariantRecord; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -18,11 +18,11 @@ public class VariantContextTestUtil { public static final Allele REF = Allele.REF_T; - public static VariantGeneRecord createVariantContext(List genotypes, String vepData) { + public static VariantRecord createVariantContext(List genotypes, String vepData) { return createVariantContext(genotypes, vepData, "1"); } - public static VariantGeneRecord createVariantContext(List genotypes, String vepData, String contig) { + public static VariantRecord createVariantContext(List genotypes, String vepData, String contig) { VariantContextBuilder builder = new VariantContextBuilder(); builder.chr(contig); builder.start(12345); @@ -31,7 +31,7 @@ public static VariantGeneRecord createVariantContext(List genotypes, S builder.genotypes(genotypes); builder.attribute("CSQ", vepData); - return new VariantGeneRecord(builder.make(), Set.of(ALT_A,ALT_G,ALT_N), new GeneInfo("GENE1", "SOURCE", emptySet())); + return new VariantRecord(builder.make(), Set.of(ALT_A,ALT_G,ALT_N), Set.of(new GeneInfo("GENE1", "SOURCE", emptySet()))); } public static Genotype createGenotype(String sample, String gt) { From 0715ed5f8543d9cf51fe72c2f4766143c163971b Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 24 Sep 2024 16:22:56 +0200 Subject: [PATCH 11/28] Fix IT tests --- .../vcf/inheritance/matcher/Annotator.java | 2 +- src/test/resources/expected_noParents.vcf | 18 +++++++------- src/test/resources/expected_noPed.vcf | 24 +++++++++---------- .../resources/expected_noVEPinheritance.vcf | 14 +++++------ src/test/resources/expected_probands.vcf | 18 +++++++------- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 84439d7..63a4311 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -98,7 +98,7 @@ private List getMatchingGenes(Set pedigreeInhe for (GeneInfo geneInfo : geneInfos) { if (geneInfo.inheritanceModes().stream().anyMatch(geneMode -> isMatch(geneMode, pedigreeInheritanceMatch.inheritanceMode())) && pedigreeInheritanceMatch.inheritanceMode() != AR_C - || !compounds.get(geneInfo).isEmpty()) { + || compounds.get(geneInfo) != null && !compounds.get(geneInfo).isEmpty()) { results.add(geneInfo.geneId()); } } diff --git a/src/test/resources/expected_noParents.vcf b/src/test/resources/expected_noParents.vcf index f18256a..4e9c4d5 100644 --- a/src/test/resources/expected_noParents.vcf +++ b/src/test/resources/expected_noParents.vcf @@ -41,21 +41,21 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,::ID2:0,1 0/0:50 0/0:50 1/0:50:AD_IP,AD_IP:,::ID2:0,1 0/0:50 1/0:50 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2:1 0/0:50 0/0:50 1/0:50:AD_IP:::ID2:1 0/0:50 1/0:50 1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP,AR&AD_IP:,::ID1,ID2:1,1 0/1:50 0/1:50 1/0:50:AD,AD:,::ID2:0,1 1/0:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:::ID1,ID2:1 0/1:50 0/1:50 1/0:50:AD:::ID2:1 1/0:50 0/0:50 1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::::0 1/0:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP:::ID4:1 0/0:50 1/0:50 1/0:50:AD:::ID4:1 1/0:50 0/0:50 2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP:::ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:::0,0 0/0:50 0/0:50 1/0:50:XLD,XLD:,:::0,0 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID6 ./.:50 0/0:50 1/0:50:XLD:::ID6 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 -Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID9 ./.:50 0/0:50 1/0:50:YL:::ID9 ./.:50 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:::ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 +Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL ./.:50 0/0:50 1/0:50:YL ./.:50 0/0:50 Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID10 ./.:50 0/0:50 1/0:50:YL:::ID10 ./.:50 0/0:50 Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11:1 .:50 0:50 1:50:YL:::ID11:1 .:50 0:50 -MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT:::ID12 .:50 0:50 1:50:MT:::ID12 .:50 0:50 +MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT .:50 0:50 1:50:MT .:50 0:50 diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index bffe9c2..adf9b43 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -41,21 +41,21 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,::ID2:0,1 0/0:50:,:,:::0,0 0/0:50:,:,:::0,0 1/0:50:AD,AD:,::ID2:0,1 0/0:50:,:,:::0,0 1/0:50:AD,AD:,::ID2:0,1 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID2:1 0/0:50:::::0 1/0:50:AD:::ID2:1 1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50:AR_C:1_123460_C_G::ID3 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 -1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID3:1 1/1:50:AR&AD:::ID3:1 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR&AD:::ID3:1 0/0:50:::::0 -1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD,AR&AD:,::ID1,ID2:1,1 0/1:50:AD,AD:,::ID2:0,1 0/1:50:AD,AD:,::ID2:0,1 1/0:50:AD,AD:,::ID2:0,1 1/0:50:AD,AD:,::ID2:0,1 0/0:50:,:,:::0,0 -1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD&AR_C:1_123458_C_G::ID3:1 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD::::0 1/1:50:AR,AD::::0 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR,AD::::0 0/0:50:::::0 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID1,ID2:1 0/1:50:AD:::ID2:1 0/1:50:AD:::ID2:1 1/0:50:AD:::ID2:1 1/0:50:AD:::ID2:1 0/0:50:::::0 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD,AR_C:1_123458_C_G::ID3,ID3:1 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID4:1 0/0:50:::::0 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 0/0:50:::::0 2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 -4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 -4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 -X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:::0,0 0/0:50:,:,:::0,0 0/0:50:,:,:::0,0 1/0:50:XLD,XLD:,:::0,0 0/0:50:,:,:::0,0 1/0:50:XLD,XLD:,:::0,0 -X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID6 ./.:50:::::0 0/0:50:::::0 1/0:50:XLD:::ID6 1/0:50:XLD:::ID6 0/0:50:::::0 -X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50:::::0 -Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 -Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 1/0:50:::::0 ./.:50:::::0 0/0:50:::::0 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50:::::0 0/0:50:::::0 1/0:50:XLD::::0 0/0:50:::::0 1/0:50:XLD::::0 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50:::::0 0/0:50:::::0 1/0:50:XLD 1/0:50:XLD 0/0:50:::::0 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50:::::0 +Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL ./.:50:::::0 0/0:50:::::0 1/0:50:YL ./.:50:::::0 0/0:50:::::0 +Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID10 ./.:50:::::0 0/0:50:::::0 1/0:50:YL:::ID10 ./.:50:::::0 0/0:50:::::0 Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11:1 .:50:::::0 0:50:::::0 1:50:YL:::ID11:1 .:50:::::0 0:50:::::0 -MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT:::ID12 .:50:::::0 0:50:::::0 1:50:MT:::ID12 .:50:::::0 0:50:::::0 +MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT .:50:::::0 0:50:::::0 1:50:MT .:50:::::0 0:50:::::0 diff --git a/src/test/resources/expected_noVEPinheritance.vcf b/src/test/resources/expected_noVEPinheritance.vcf index 445e14a..ba73bff 100644 --- a/src/test/resources/expected_noVEPinheritance.vcf +++ b/src/test/resources/expected_noVEPinheritance.vcf @@ -39,10 +39,10 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,:1:ID1,ID2 0/0:50:AD,AD:,::ID1,ID2 0/0:50:AD,AD:,::ID1,ID2 1/0:50:AD_IP,AD_IP:,::ID1,ID2 0/0:50 1/0:50:AD_IP,AD_IP:,::ID1,ID2 -1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID3 ./.:50:AD:::ID3 0/0:50:AD:::ID3 1/0:50:AD:::ID3 1/0:50 0/0:50:AD:::ID3 -1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0:ID3 1/1:50:AD_IP:::ID3 0/1:50:AD_IP:::ID3 1/0:50:AD:::ID3 1/1:50 0/0:50:AD:::ID3 -1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP,AR&AD_IP:,:0:ID1,ID2 0/1:50:AR&AD_IP,AR&AD_IP:,::ID1,ID2 0/1:50:AR&AD_IP,AR&AD_IP:,::ID1,ID2 1/0:50:AD,AD:,::ID1,ID2 1/0:50 0/0:50:AD,AD:,::ID1,ID2 -X 123457 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|,G|GENE6|EntrezGene|ID6| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:1:ID4,ID6 0/0:50:XLD,XLD:,::ID4,ID6 0/0:50:XLD,XLD:,::ID4,ID6 1/0:50:XLD,XLD:,::ID4,ID6 0/0:50 1/0:50:XLD,XLD:,::ID4,ID6 -X 123458 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID5 ./.:50:XLD:::ID5 0/0:50:XLD:::ID5 1/0:50:XLD:::ID5 1/0:50 0/0:50:XLD:::ID5 -X 123459 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::0:ID5 0/1:50:XLD&XLR:::ID5 0/1:50:XLD&XLR:::ID5 1/0:50:XLD:::ID5 1/0:50 0/0:50:XLD:::ID5 +1 123457 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1 0/0:50:AD 0/0:50:AD 1/0:50:AD_IP 0/0:50 1/0:50:AD_IP +1 123458 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD ./.:50:AD 0/0:50:AD 1/0:50:AD 1/0:50 0/0:50:AD +1 123459 . C G . PASS CSQ=G|GENE3|EntrezGene|ID3| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0 1/1:50:AD_IP 0/1:50:AD_IP 1/0:50:AD 1/1:50 0/0:50:AD +1 123459 . C G . PASS CSQ=G|GENE1|EntrezGene|ID1|,G|GENE2|EntrezGene|ID2| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::0 0/1:50:AR,AD_IP 0/1:50:AR,AD_IP 1/0:50:AD 1/0:50 0/0:50:AD +X 123457 . C G . PASS CSQ=G|GENE4|EntrezGene|ID4|,G|GENE6|EntrezGene|ID6| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::1 0/0:50:XLD 0/0:50:XLD 1/0:50:XLD 0/0:50 1/0:50:XLD +X 123458 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50:XLD 0/0:50:XLD 1/0:50:XLD 1/0:50 0/0:50:XLD +X 123459 . C G . PASS CSQ=G|GENE5|EntrezGene|ID5| GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::0 0/1:50:XLD,XLR 0/1:50:XLD,XLR 1/0:50:XLD 1/0:50 0/0:50:XLD diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index 84fe471..fd1d9a6 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -41,21 +41,21 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AD:,:1:ID2:0, 0/0:50 0/0:50 1/0:50:AD_IP,AD_IP:,::ID2:0,1 0/0:50 1/0:50 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID2 0/0:50 0/0:50 1/0:50:AD_IP:::ID2:1 0/0:50 1/0:50 1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP,AR&AD_IP:,:0:ID1,ID2:1,1 0/1:50 0/1:50 1/0:50:AD,AD:,::ID2:0,1 1/0:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::0:ID2,ID1:1 0/1:50 0/1:50 1/0:50:AD:::ID2:1 1/0:50 0/0:50 1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0::0 1/0:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0:ID4:1 0/0:50 1/0:50 1/0:50:AD:::ID4:1 1/0:50 0/0:50 2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD_IP::1:ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR&AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD,XLD:,:1::0,0 0/0:50 0/0:50 1/0:50:XLD,XLD:,:::0,0 0/0:50 1/0:50 -X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD:::ID6 ./.:50 0/0:50 1/0:50:XLD:::ID6 1/0:50 0/0:50 -X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD&XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 -Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL::1:ID9 ./.:50 0/0:50 1/0:50:YL:::ID9 ./.:50 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::1::0 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD::1::0 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::1::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 +Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL::1 ./.:50 0/0:50 1/0:50:YL ./.:50 0/0:50 Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL::1:ID10 ./.:50 0/0:50 1/0:50:YL:::ID10 ./.:50 0/0:50 Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL::1:ID11:1 .:50 0:50 1:50:YL:::ID11:1 .:50 0:50 -MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT:::ID12 .:50 0:50 1:50:MT:::ID12 .:50 0:50 +MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT .:50 0:50 1:50:MT .:50 0:50 From 6d2cc2574eb4bde9a93f3b816876d94afdd69e9e Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 24 Sep 2024 16:55:57 +0200 Subject: [PATCH 12/28] Fix IT tests --- .../vcf/inheritance/matcher/Annotator.java | 15 ++++++++------- src/test/resources/expected_noPed.vcf | 4 ++-- src/test/resources/expected_probands.vcf | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 63a4311..1d3f2b9 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -68,7 +68,7 @@ VariantContext annotateInheritance(VariantRecord variantRecord, Collection vig = new ArrayList<>(); + Set vig = new HashSet<>(); Set compounds = getCompoundStrings(inheritanceResult.getCompounds()); String vic = inheritanceResult.getCompounds().isEmpty() ? "" : String.join(",", compounds); MatchEnum match = getMatch(inheritanceResult, variantRecord); @@ -81,7 +81,7 @@ private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", vi)); genotypeBuilder.attribute(INHERITANCE_MATCH, vim); genotypeBuilder.attribute(POSSIBLE_COMPOUND, vic); - genotypeBuilder.attribute(MATCHING_GENES, String.join(",", vig)); + genotypeBuilder.attribute(MATCHING_GENES, vig.stream().sorted().collect(Collectors.joining(","))); genotypeBuilder.attribute(DENOVO, mapDenovoValue(inheritanceResult, sample)); return genotypeBuilder.make(); } @@ -92,8 +92,8 @@ private Set getCompoundStrings(Map> c return result; } - private List getMatchingGenes(Set pedigreeInheritanceMatches, Set geneInfos, Map> compounds) { - List results = new ArrayList<>(); + private Set getMatchingGenes(Set pedigreeInheritanceMatches, Set geneInfos, Map> compounds) { + Set results = new HashSet<>(); for (PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { for (GeneInfo geneInfo : geneInfos) { if (geneInfo.inheritanceModes().stream().anyMatch(geneMode -> isMatch(geneMode, @@ -174,12 +174,13 @@ public MatchEnum getMatch(InheritanceResult inheritanceResult, VariantRecord var } private static Boolean isMatch(Set pedigreeInheritanceMatches, InheritanceMode geneInheritanceMode) { - boolean isMatch = false; for (PedigreeInheritanceMatch pedigreeInheritanceMatch : pedigreeInheritanceMatches) { InheritanceMode pedigreeInheritanceMode = pedigreeInheritanceMatch.inheritanceMode(); - isMatch = isMatch(geneInheritanceMode, pedigreeInheritanceMode); + if(isMatch(geneInheritanceMode, pedigreeInheritanceMode)){ + return true; + } } - return isMatch; + return false; } private static boolean isMatch(InheritanceMode geneInheritanceMode, InheritanceMode pedigreeInheritanceMode) { diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index adf9b43..1cea6ab 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -43,9 +43,9 @@ #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID2:1 0/0:50:::::0 1/0:50:AD:::ID2:1 1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50:AR_C:1_123460_C_G::ID3 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 -1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD::::0 1/1:50:AR,AD::::0 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR,AD::::0 0/0:50:::::0 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID3:1 1/1:50:AR,AD:::ID3:1 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR,AD:::ID3:1 0/0:50:::::0 1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID1,ID2:1 0/1:50:AD:::ID2:1 0/1:50:AD:::ID2:1 1/0:50:AD:::ID2:1 1/0:50:AD:::ID2:1 0/0:50:::::0 -1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD,AR_C:1_123458_C_G::ID3,ID3:1 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD,AR_C:1_123458_C_G::ID3:1 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID4:1 0/0:50:::::0 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 0/0:50:::::0 2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index fd1d9a6..2812a3f 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -44,14 +44,14 @@ 1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID2 0/0:50 0/0:50 1/0:50:AD_IP:::ID2:1 0/0:50 1/0:50 1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 -1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::0:ID2,ID1:1 0/1:50 0/1:50 1/0:50:AD:::ID2:1 1/0:50 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::0:ID1,ID2:1 0/1:50 0/1:50 1/0:50:AD:::ID2:1 1/0:50 0/0:50 1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0::0 1/0:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0:ID4:1 0/0:50 1/0:50 1/0:50:AD:::ID4:1 1/0:50 0/0:50 2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0 0/0:50 1/0:50 1/0:50:AD 1/0:50 0/0:50 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::1::0 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 -4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD::1::0 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::1:ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::1::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 From 293d51915d8b8c7214562680d12000922fb1c1b4 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 25 Sep 2024 09:18:47 +0200 Subject: [PATCH 13/28] Fix variant filtering --- .../matcher/AppCommandLineRunner.java | 1 - .../matcher/InheritanceService.java | 15 +++---- .../inheritance/matcher/VariantRecord.java | 3 -- .../matcher/VcfRecordFactoryImpl.java | 2 +- .../vcf/inheritance/matcher/AppIT.java | 4 +- src/test/resources/expected_noParents.vcf | 3 ++ src/test/resources/expected_noPed.vcf | 39 ++++++++++--------- src/test/resources/expected_probands.vcf | 3 ++ src/test/resources/integration.vcf | 3 ++ 9 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java index 4bba679..58faa50 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java @@ -115,7 +115,6 @@ private Settings mapSettings(CommandLine commandLine) { .build(); } - //TODO: validate private Set mapPathogenicityClasses(String optionValue) { return Set.of(optionValue.split(",")); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index 9b78188..a7926dc 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -90,14 +90,15 @@ private void matchPedigree(VariantRecord variantRecord, Collection ped inheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(AD_IP, isAdIpMatch == POTENTIAL)); } } - } - matchCompounds(variantRecord, vcfRecordGeneInfoMap, pedigree, inheritanceResult); - Map denovoResult = new HashMap<>(); - pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> - denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); - inheritanceResult.setDenovo(denovoResult); - inheritanceResultMap.put(pedigree, inheritanceResult); + matchCompounds(variantRecord, vcfRecordGeneInfoMap, pedigree, inheritanceResult); + + Map denovoResult = new HashMap<>(); + pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> + denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); + inheritanceResult.setDenovo(denovoResult); + inheritanceResultMap.put(pedigree, inheritanceResult); + } } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java index 031f1e1..07a7210 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java @@ -14,9 +14,6 @@ public EffectiveGenotype getGenotype(String sampleId) { if (gt == null) { return null; } - if(pathogenicAlleles.isEmpty()){ - pathogenicAlleles.addAll(variantContext.getAlternateAlleles()); - } return new EffectiveGenotype(gt); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java index 21f58db..fc816de 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java @@ -43,7 +43,7 @@ private Set getPathogenicAlleles(VariantContext variantContext, VepMetad for (int i = 1; i <= variantContext.getAlternateAlleles().size(); i++) { Allele allele = variantContext.getAlleles().get(i); - if (isAllelePathogenic(variantContext, vepMetadata, i, pathogenicClasses)) { + if (pathogenicClasses.isEmpty() || isAllelePathogenic(variantContext, vepMetadata, i, pathogenicClasses)) { pathogenicAlleles.add(allele); } } diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java index e1f37d4..627eff3 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java @@ -37,7 +37,7 @@ void testNoPed() throws IOException { String inputFile = ResourceUtils.getFile("classpath:integration.vcf").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pc", "P"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); @@ -54,7 +54,7 @@ void testProband() throws IOException { String pedigree = ResourceUtils.getFile("classpath:pedigree_complex.ped").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-pc","P:LP,P;B:LB,B;V:VUS"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-pc","P,B"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); diff --git a/src/test/resources/expected_noParents.vcf b/src/test/resources/expected_noParents.vcf index 4e9c4d5..8fbe344 100644 --- a/src/test/resources/expected_noParents.vcf +++ b/src/test/resources/expected_noParents.vcf @@ -52,6 +52,9 @@ 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:::ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2a:1 0/0:50 0/0:50 1/0:50:AD_IP:::ID2a:1 0/0:50 1/0:50 +5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index 1cea6ab..377a453 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -41,21 +41,24 @@ ##contig= ##fileDate=20200320 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Patient Mother Father Patient2 Mother2 Father2 -1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID2:1 0/0:50:::::0 1/0:50:AD:::ID2:1 -1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50:AR_C:1_123460_C_G::ID3 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 -1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID3:1 1/1:50:AR,AD:::ID3:1 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR,AD:::ID3:1 0/0:50:::::0 -1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID1,ID2:1 0/1:50:AD:::ID2:1 0/1:50:AD:::ID2:1 1/0:50:AD:::ID2:1 1/0:50:AD:::ID2:1 0/0:50:::::0 -1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD,AR_C:1_123458_C_G::ID3:1 0/0:50:::::0 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50:::::0 -1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID4:1 0/0:50:::::0 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 0/0:50:::::0 -2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 -3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50:::::0 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50:::::0 -4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 -4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 -4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 0/0:50:::::0 0/0:50:::::0 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50:::::0 -X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50:::::0 0/0:50:::::0 1/0:50:XLD::::0 0/0:50:::::0 1/0:50:XLD::::0 -X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50:::::0 0/0:50:::::0 1/0:50:XLD 1/0:50:XLD 0/0:50:::::0 -X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50:::::0 -Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL ./.:50:::::0 0/0:50:::::0 1/0:50:YL ./.:50:::::0 0/0:50:::::0 -Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID10 ./.:50:::::0 0/0:50:::::0 1/0:50:YL:::ID10 ./.:50:::::0 0/0:50:::::0 -Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11:1 .:50:::::0 0:50:::::0 1:50:YL:::ID11:1 .:50:::::0 0:50:::::0 -MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT .:50:::::0 0:50:::::0 1:50:MT .:50:::::0 0:50:::::0 +1 123457 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2:1 0/0:50 0/0:50 1/0:50:AD:::ID2:1 0/0:50 1/0:50:AD:::ID2:1 +1 123458 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID3:1 1/1:50:AR,AD:::ID3:1 0/1:50:AD::::0 1/0:50:AD::::0 1/1:50:AR,AD:::ID3:1 0/0:50 +1 123459 . C G . PASS CSQ=P|1|G|GENE1|EntrezGene|ID1|1|AR,P|1|G|GENE2|EntrezGene|ID2||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID1,ID2:1 0/1:50:AD:::ID2:1 0/1:50:AD:::ID2:1 1/0:50:AD:::ID2:1 1/0:50:AD:::ID2:1 0/0:50 +1 123460 . C G . PASS CSQ=P|1|G|GENE3|EntrezGene|ID3|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 1/0:50:AD,AR_C:1_123458_C_G::ID3:1 0/0:50 1/0:50:AD::::0 1/0:50:AD::::0 0/0:50 +1 123461 . C G . PASS CSQ=P|1|G|GENE4|EntrezGene|ID4|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID4:1 0/0:50 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 1/0:50:AD:::ID4:1 0/0:50 +2 1 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50 +3 2 empty_gene C G . PASS CSQ=P|1|G|UNUSED_GENE_NAME|||| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD 0/0:50 1/0:50:AD 1/0:50:AD 1/0:50:AD 0/0:50 +4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50 +4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50 +4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID8:1 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50:AD:::ID8:1 0/0:50 +5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2a:1 0/0:50 0/0:50 1/0:50:AD:::ID2a:1 0/0:50 1/0:50:AD:::ID2a:1 +5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 +5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 +X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50:XLD::::0 +X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50:XLD 0/0:50 +X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50 +Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL ./.:50 0/0:50 1/0:50:YL ./.:50 0/0:50 +Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:YL:::ID10 ./.:50 0/0:50 1/0:50:YL:::ID10 ./.:50 0/0:50 +Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP:VI:VIC:VID:VIG:VIM 1:50:YL:::ID11:1 .:50 0:50 1:50:YL:::ID11:1 .:50 0:50 +MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP:VI:VIC:VID:VIG:VIM 1:50:MT .:50 0:50 1:50:MT .:50 0:50 diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index 2812a3f..f11c574 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -52,6 +52,9 @@ 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::1:ID8:1 1/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD::1:ID8 0/0:50 0/0:50 1/0:50:AD:::ID8:1 1/0:50 0/0:50 +5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID2a 0/0:50 0/0:50 1/0:50:AD_IP:::ID2a:1 0/0:50 1/0:50 +5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::1::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 diff --git a/src/test/resources/integration.vcf b/src/test/resources/integration.vcf index ef07ff3..09ef286 100644 --- a/src/test/resources/integration.vcf +++ b/src/test/resources/integration.vcf @@ -47,6 +47,9 @@ 4 123457 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 4 123458 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 1/0:50 0/0:50 1/0:50 1/0:50 0/0:50 4 123459 . C G . PASS CSQ=P|1|G|GENE8|EntrezGene|ID8||AD GT:DP 1/1:50 0/0:50 0/0:50 1/0:50 1/0:50 0/0:50 +5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 +5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 +5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 From a6287681d420cb86e4db8298af256c802e6a838e Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 25 Sep 2024 12:51:38 +0200 Subject: [PATCH 14/28] Add additional test cases --- .../matcher/checker/DeNovoChecker.java | 116 +++++++++--------- .../matcher/checker/XlrChecker.java | 2 +- src/test/resources/ADtests.tsv | 6 +- src/test/resources/ARTests.tsv | 16 ++- src/test/resources/DenovoTests.tsv | 17 ++- src/test/resources/XldTests.tsv | 10 +- src/test/resources/XlrTests.tsv | 14 ++- src/test/resources/expected_noParents.vcf | 6 + src/test/resources/expected_noPed.vcf | 6 + src/test/resources/expected_probands.vcf | 6 + src/test/resources/integration.vcf | 8 +- 11 files changed, 141 insertions(+), 66 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java index 622d98e..ef68ef8 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java @@ -1,8 +1,10 @@ package org.molgenis.vcf.inheritance.matcher.checker; +import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.inheritance.matcher.util.InheritanceUtils.*; +import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.ContigUtils; import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; import org.molgenis.vcf.inheritance.matcher.VariantRecord; @@ -11,6 +13,10 @@ import org.molgenis.vcf.utils.sample.model.Sex; import org.springframework.stereotype.Component; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + @Component public class DeNovoChecker { @@ -37,10 +43,10 @@ public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { } private static MatchEnum checkMaleXVariant(EffectiveGenotype probandGt, EffectiveGenotype motherGt) { - if(probandGt == null){ + if (probandGt == null || probandGt.isNoCall()) { return POTENTIAL; } else if (probandGt.hasAltAllele()) { - if (motherGt != null && motherGt.hasAltAllele()) { + if (motherGt != null && hasSameAltAlleles(probandGt, motherGt)) { return FALSE; } else if (motherGt != null && motherGt.isHomRef()) { return TRUE; @@ -61,10 +67,10 @@ private static MatchEnum checkYLinkedVariant(Sample proband, EffectiveGenotype p private static MatchEnum checkYLinkedVariantMale(EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { if (probandGt.hasAltAllele()) { - if (fatherGt.hasAltAllele()) { + if (hasSameAltAlleles(probandGt, fatherGt)) { return FALSE; } else { - return (!fatherGt.hasAltAllele() && !hasMissing(fatherGt)) ? TRUE : POTENTIAL; + return (!hasSameAltAlleles(probandGt, fatherGt) && !hasMissing(fatherGt)) ? TRUE : POTENTIAL; } } else if (hasMissing(probandGt)) { return fatherGt.hasAltAllele() ? FALSE : POTENTIAL; @@ -72,19 +78,24 @@ private static MatchEnum checkYLinkedVariantMale(EffectiveGenotype probandGt, Ef return FALSE; } + private static boolean hasSameAltAlleles(EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { + return probandGt.getAlleles().stream().filter(allele -> allele.isCalled() && + allele.isNonReference()).allMatch(allele -> fatherGt.getAlleles().contains(allele)); + } + private static MatchEnum checkMtVariant(EffectiveGenotype probandGt, EffectiveGenotype motherGt) { - if (probandGt == null) { + if (probandGt == null || probandGt.isNoCall()) { return POTENTIAL; - }else if (probandGt.hasAltAllele()) { - if (motherGt != null && motherGt.hasAltAllele()) { + } else if (probandGt.hasAltAllele()) { + if (motherGt != null && hasSameAltAlleles(probandGt, motherGt) && !motherGt.hasReference()) { return FALSE; - } else if (motherGt != null && !motherGt.hasAltAllele() && motherGt.isCalled() && !motherGt.isMixed()) { + } else if (motherGt != null && !hasSameAltAlleles(probandGt, motherGt) && motherGt.isCalled() && !motherGt.isMixed()) { return TRUE; } else { return POTENTIAL; } - } else if (probandGt.isNoCall() || probandGt.isMixed()) { - if (motherGt.hasAltAllele()) { + } else if (probandGt.hasMissingAllele()) { + if (probandGt.hasAltAllele() && hasSameAltAlleles(probandGt, motherGt)) { return FALSE; } else { return POTENTIAL; @@ -94,64 +105,57 @@ private static MatchEnum checkMtVariant(EffectiveGenotype probandGt, EffectiveGe } private MatchEnum checkRegular(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { - MatchEnum result = FALSE; - if (probandGt != null) { - if (probandGt.isHom()) { - result = checkHomozygote(probandGt, fatherGt, motherGt); - } else if (probandGt.isHet()) { - result = checkHetrozygote(probandGt, fatherGt, motherGt); - } else if (probandGt.isMixed()) { - result = checkMixed(probandGt, fatherGt, motherGt); - } else { - result = (motherGt.hasAltAllele() && fatherGt.hasAltAllele()) ? FALSE : POTENTIAL; - } + Set result = new HashSet<>(); + if (probandGt == null || probandGt.isNoCall()) { + return POTENTIAL; } - return result; + List alleles = probandGt.getAlleles(); + if (alleles.size() != 2) { + throw new UnsupportedOperationException("Checking 'regular' denovo calles requires diploid genotypes."); + } + Allele allele1 = alleles.get(0); + Allele allele2 = alleles.get(1); + result.add(checkAlleles(fatherGt, motherGt, allele1, allele2)); + + return merge(result); } - private static MatchEnum checkMixed(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { - MatchEnum result; - if (probandGt.hasAltAllele()) { - if (motherGt.isHomRef() && fatherGt.isHomRef()) { - result = TRUE; - } else if (motherGt.hasAltAllele() && fatherGt.hasAltAllele()) { - result = FALSE; - } else { - result = POTENTIAL; - } - } else { - if (motherGt.hasAltAllele() || fatherGt.hasAltAllele()) { - result = FALSE; - } else { - result = POTENTIAL; - } + private static MatchEnum checkAlleles(EffectiveGenotype fatherGt, EffectiveGenotype motherGt, Allele allele1, Allele allele2) { + if(allele1.isNoCall() || allele2.isNoCall()) { + return checkPartialCalls(fatherGt, motherGt, allele1, allele2); + } + else if ((containsAlleleOrRef(motherGt, allele1) && containsAlleleOrRef(fatherGt, allele2)) || + (containsAlleleOrRef(motherGt, allele2) && containsAlleleOrRef(fatherGt, allele1))) { + return FALSE; + } else if (containsAlleleOrNoCall(motherGt, allele1) && (containsAlleleOrNoCall(fatherGt, allele2)) || + containsAlleleOrNoCall(motherGt, allele2) && (containsAlleleOrNoCall(fatherGt, allele1))) { + return POTENTIAL; } - return result; + return TRUE; } - private static MatchEnum checkHetrozygote(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { - if (probandGt.hasAltAllele()) { - if (motherGt.isHomRef() && fatherGt.isHomRef()) { - return TRUE; - } else if (motherGt.hasAltAllele() || fatherGt.hasAltAllele()) { - return FALSE; + private static MatchEnum checkPartialCalls(EffectiveGenotype fatherGt, EffectiveGenotype motherGt, Allele allele1, Allele allele2) { + if (allele1.isNoCall() && allele2.isCalled()) { + if (containsAlleleOrNoCall(motherGt, allele2) || containsAlleleOrNoCall(fatherGt, allele2)) { + return POTENTIAL; } else { + return TRUE; + } + } else if (allele2.isNoCall() && allele1.isCalled()) { + if (containsAlleleOrNoCall(motherGt, allele1) || containsAlleleOrNoCall(fatherGt, allele1)) { return POTENTIAL; + } else { + return TRUE; } } return FALSE; } - private static MatchEnum checkHomozygote(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { - if (probandGt.hasAltAllele()) { - if (motherGt.isHomRef() || fatherGt.isHomRef()) { - return TRUE; - } else if (motherGt.hasAltAllele() && fatherGt.hasAltAllele()) { - return FALSE; - } else { - return POTENTIAL; - } - } - return FALSE; + private static boolean containsAlleleOrRef(EffectiveGenotype genotype, Allele allele) { + return allele.isReference() || genotype.getAlleles().contains(allele); + } + + private static boolean containsAlleleOrNoCall(EffectiveGenotype genotype, Allele allele1) { + return containsAlleleOrRef(genotype, allele1) || containsAlleleOrRef(genotype, Allele.NO_CALL); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index a25e277..32fc643 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -32,7 +32,7 @@ protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map allele.isCalled() && affectedAlleles.contains(allele))) { + allele -> allele.isCalled() && allele.isNonReference() && affectedAlleles.contains(allele))) { matches.add(FALSE); } else { matches.add(POTENTIAL); diff --git a/src/test/resources/ADtests.tsv b/src/test/resources/ADtests.tsv index 869eeb3..ad1266b 100644 --- a/src/test/resources/ADtests.tsv +++ b/src/test/resources/ADtests.tsv @@ -33,4 +33,8 @@ MixedParents5 0/1 AFFECTED MALE ./1 UNAFFECTED 0/0 UNAFFECTED 0/0 UNAFFECTED fal MixedParents6 0/1 AFFECTED MALE ./0 UNAFFECTED 0/1 UNAFFECTED 0/0 UNAFFECTED false multiallelic_denovo 0/2 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED true multiallelic_denovo_fatherHas1 1/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED possible -multiallelic_father_has_it 0/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED false \ No newline at end of file +multiallelic_father_has_it 0/2 AFFECTED MALE 0/2 UNAFFECTED 0/0 UNAFFECTED false +multiallelic_father_has_other 0/2 AFFECTED MALE 0/1 UNAFFECTED 0/0 UNAFFECTED possible +multiallelic_brother_has_it 0/2 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED 0/2 UNAFFECTED false +multiallelic 0/2 AFFECTED MALE 0/1 UNAFFECTED 0/0 UNAFFECTED 0/1 AFFECTED false +multiallelic_2denovo 0/2 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED 0/1 AFFECTED true \ No newline at end of file diff --git a/src/test/resources/ARTests.tsv b/src/test/resources/ARTests.tsv index 7d0b34c..945be0f 100644 --- a/src/test/resources/ARTests.tsv +++ b/src/test/resources/ARTests.tsv @@ -22,4 +22,18 @@ Mixed7 1/. AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED ./. AFFECTED possible Mixed8 ./. AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED 0/. UNAFFECTED possible Unknown1 1/1 AFFECTED MALE 1/0 MISSING 0/0 UNAFFECTED possible Unknown2 1/1 AFFECTED MALE 1/1 MISSING 0/0 UNAFFECTED possible -Unknown1 1/1 AFFECTED MALE 0/0 MISSING 1/1 UNAFFECTED false \ No newline at end of file +Unknown1 1/1 AFFECTED MALE 0/0 MISSING 1/1 UNAFFECTED false +MultiAllelic1 0/1 AFFECTED MALE 2/2 UNAFFECTED 0/0 UNAFFECTED false +MultiAllelic2 1/1 AFFECTED MALE 0/2 UNAFFECTED 2/0 UNAFFECTED true +MultiAllelic3 1/2 AFFECTED MALE 2/2 UNAFFECTED 1/1 UNAFFECTED false +MultiAllelic4 2/2 AFFECTED MALE 1/1 UNAFFECTED 1/0 UNAFFECTED possible +MultiAllelic5 2/2 AFFECTED MALE 0/1 UNAFFECTED 1/0 UNAFFECTED true +MultiAllelic6 1/1 AFFECTED MALE 2/2 UNAFFECTED 0/0 UNAFFECTED possible +MultiAllelic7 1/1 AFFECTED MALE 1/2 UNAFFECTED 2/2 UNAFFECTED possible +MultiAllelic8 2/1 AFFECTED MALE 0/0 UNAFFECTED 0/0 UNAFFECTED 1/2 UNAFFECTED false +MultiAllelic9 1/1 AFFECTED MALE 0/2 UNAFFECTED 2/0 UNAFFECTED 3/3 UNAFFECTED possible +MultiAllelic10 1/2 AFFECTED MALE 0/1 UNAFFECTED 1/1 UNAFFECTED 2/2 UNAFFECTED false +MultiAllelic11 2/2 AFFECTED MALE 1/1 UNAFFECTED 1/0 UNAFFECTED 1/2 UNAFFECTED possible +MultiAllelic12 2/2 AFFECTED MALE 1/1 UNAFFECTED 1/0 UNAFFECTED 1/2 AFFECTED false +MultiAllelic13 1/1 AFFECTED MALE 2/2 UNAFFECTED 0/0 UNAFFECTED 1/2 AFFECTED false +MultiAllelic14 1/1 AFFECTED MALE 1/2 UNAFFECTED 2/2 UNAFFECTED 1/2 AFFECTED false diff --git a/src/test/resources/DenovoTests.tsv b/src/test/resources/DenovoTests.tsv index 355f185..aa4db19 100644 --- a/src/test/resources/DenovoTests.tsv +++ b/src/test/resources/DenovoTests.tsv @@ -26,7 +26,7 @@ XMotherMotherPartialRefFatherAlt 1/0 FEMALE 1 ./0 X false ProbandPartial1 1/. FEMALE 0 0/0 X true ProbandPartial2 1/. FEMALE 0 1/0 X possible ProbandPartial3 1/. FEMALE 0 1/. X possible -ProbandPartial4 1/. FEMALE 1 1/. X false +ProbandPartial4 1/. FEMALE 1 1/. X possible ProbandPartial5 1/. FEMALE 0 0/. X possible ProbandPartial6 ./0 FEMALE 0 0/0 X possible ProbandMissing ./. FEMALE 0 0/0 X possible @@ -52,15 +52,24 @@ MT1 1 MALE 1 0 MT true MT2 1 FEMALE 1 1 MT false MT3 1 MALE 1 . MT possible MT4 . FEMALE 1 0 MT possible -MT5 . MALE 1 1 MT false +MT5 . MALE 1 1 MT possible MT6 . FEMALE 1 . MT possible MT1dip 1/0 MALE 1/1 0/0 MT true MT2dip ./0 FEMALE 1/1 0/0 MT possible MT3dip 1/1 MALE 1/1 0/0 MT true -MT4dip ./1 FEMALE 1/1 0/1 MT false +MT4dip ./1 FEMALE 1/1 0/1 MT possible MT5dip 1/0 MALE 1/1 ./. MT possible MT6dip 1/1 FEMALE 1/1 ./0 MT possible MT7dip 1/0 MALE 1/1 1/1 MT false MT8dip ./1 FEMALE 1/1 ./. MT possible MT9dip ./1 MALE 1/1 1/1 MT false -MT10dip ./0 FEMALE 1/1 0/0 MT possible \ No newline at end of file +MultiAllelic1 2/1 FEMALE 1/2 2/0 1 false +MultiAllelic2 2/0 FEMALE 1/0 1/0 1 true +MultiAllelic3 1/2 FEMALE 1/2 0/0 1 true +MultiAllelicX1 1/1 FEMALE 2/2 1/1 X true +MultiAllelicX2 1 MALE 2 1/0 X false +MultiAllelicMT 2 MALE 2 0/0 MT true +MultiAllelicY1 1/2 MALE 1/1 0/0 Y true +MultiAllelicY2 2 MALE 1 0/0 Y true +MultiAllelicY3 1/2 MALE 1/. 0/0 Y possible +MultiAllelicY4 1/2 MALE 1/3 0/0 Y true \ No newline at end of file diff --git a/src/test/resources/XldTests.tsv b/src/test/resources/XldTests.tsv index f3ac7eb..31d48b1 100644 --- a/src/test/resources/XldTests.tsv +++ b/src/test/resources/XldTests.tsv @@ -23,4 +23,12 @@ mixed5 1/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 1 UNAFFECTED false mixed6 1/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED true mixed7 0/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED possible Unknown1 1 AFFECTED MALE 0 MISSING 0/0 UNAFFECTED possible -Unknown2 1 AFFECTED MALE 1 MISSING 0/0 UNAFFECTED possible \ No newline at end of file +Unknown2 1 AFFECTED MALE 1 MISSING 0/0 UNAFFECTED possible +Multiallelic1 1 AFFECTED MALE 0 UNAFFECTED 2/0 UNAFFECTED true +Multiallelic2 2 AFFECTED MALE 2 UNAFFECTED 0/0 UNAFFECTED false +Multiallelic3 2 AFFECTED MALE 1 UNAFFECTED 1/2 UNAFFECTED false +Multiallelic4 2 AFFECTED MALE 1 UNAFFECTED 0/1 UNAFFECTED possible +Multiallelic5 1/0 AFFECTED FEMALE 2 UNAFFECTED 2/0 UNAFFECTED possible +Multiallelic6 2/0 AFFECTED FEMALE 1 UNAFFECTED 0/. UNAFFECTED possible +Multiallelic7 1/2 AFFECTED FEMALE 0 UNAFFECTED 1/1 UNAFFECTED possible +Multiallelic8 2/0 AFFECTED FEMALE 2 UNAFFECTED 0/1 UNAFFECTED false \ No newline at end of file diff --git a/src/test/resources/XlrTests.tsv b/src/test/resources/XlrTests.tsv index 1911b72..53bedcd 100644 --- a/src/test/resources/XlrTests.tsv +++ b/src/test/resources/XlrTests.tsv @@ -25,4 +25,16 @@ mixed4 1 AFFECTED MALE 0 UNAFFECTED ./0 UNAFFECTED 0 AFFECTED false mixed5 1/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED possible mixed6 0/. AFFECTED FEMALE 0 UNAFFECTED 0/0 UNAFFECTED 0 UNAFFECTED false Unknown1 1 AFFECTED MALE 0 MISSING 0/0 UNAFFECTED possible -Unknown2 1 AFFECTED MALE 1 MISSING 0/0 UNAFFECTED possible \ No newline at end of file +Unknown2 1 AFFECTED MALE 1 MISSING 0/0 UNAFFECTED possible +Multiallelic1 1 AFFECTED MALE 0 UNAFFECTED 2/2 UNAFFECTED possible +Multiallelic2 2 AFFECTED MALE 2 UNAFFECTED 0/0 UNAFFECTED false +Multiallelic3 2 AFFECTED MALE 1 UNAFFECTED 1/2 UNAFFECTED possible +Multiallelic4 2 AFFECTED MALE 1 UNAFFECTED 2/2 UNAFFECTED false +Multiallelic5 1/2 AFFECTED FEMALE 2 UNAFFECTED 2/0 UNAFFECTED false +Multiallelic6 2/2 AFFECTED FEMALE 1 UNAFFECTED 0/. UNAFFECTED possible +Multiallelic7 2/2 AFFECTED FEMALE 0 UNAFFECTED 1/1 UNAFFECTED possible +Multiallelic8 2/2 AFFECTED FEMALE 2 UNAFFECTED 0/1 UNAFFECTED false +Multiallelic9 2 AFFECTED MALE 1 UNAFFECTED 2/1 UNAFFECTED 3/3 AFFECTED possible +Multiallelic10 2/2 AFFECTED FEMALE 1 UNAFFECTED 2/3 UNAFFECTED 3/3 AFFECTED false +Multiallelic11 2/1 AFFECTED FEMALE 1 UNAFFECTED 2/3 UNAFFECTED 3/3 AFFECTED false +Multiallelic12 2/3 AFFECTED FEMALE 1 UNAFFECTED 1/3 UNAFFECTED 3/3 AFFECTED possible \ No newline at end of file diff --git a/src/test/resources/expected_noParents.vcf b/src/test/resources/expected_noParents.vcf index 8fbe344..a7a9b63 100644 --- a/src/test/resources/expected_noParents.vcf +++ b/src/test/resources/expected_noParents.vcf @@ -55,6 +55,12 @@ 5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2a:1 0/0:50 0/0:50 1/0:50:AD_IP:::ID2a:1 0/0:50 1/0:50 5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 +6 123457 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T::ID21,ID22 2/0:50 2/0:50 1/0:50:AD_IP:::ID22:1 0/0:50 1/0:50 +6 123458 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T::ID21 2/.:50 3/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +6 123459 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/3:50:AD,AR_C:6_123457_C_G/A,6_123460_C_G/A/T,6_123458_C_G/A/T::ID21 1/0:50 3/3:50 1/0:50:AD::::0 1/1:50 0/0:50 +6 123459 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP:::ID21,ID22:1 0/1:50 0/1:50 1/0:50:AD:::ID22 0/2:50 2/2:50 +6 123460 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP,AR_C:6_123459_C_G/A/T::ID21:1 1/2:50 0/3:50 2/0:50:AD::::0 2/0:50 0/0:50 +6 123461 . C G,A . PASS CSQ=P|1|G|GENE4|EntrezGene|ID21|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP:::ID21:1 2/0:50 1/0:50 2/2:50:AR,AD:::ID21:1 1/0:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index 377a453..46213fc 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -55,6 +55,12 @@ 5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID2a:1 0/0:50 0/0:50 1/0:50:AD:::ID2a:1 0/0:50 1/0:50:AD:::ID2a:1 5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 +6 123457 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T::ID21,ID22:1 2/0:50 2/0:50 1/0:50:AD:::ID22:1 0/0:50 1/0:50:AD:::ID22:1 +6 123458 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T::ID21:1 2/.:50 3/0:50 1/0:50:AD::::0 1/0:50:AD,AR_C:6_123459_C_G/A::ID21:1 0/0:50 +6 123459 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/3:50:AR,AD,AR_C:6_123457_C_G/A,6_123460_C_G/A/T,6_123458_C_G/A/T::ID21:1 1/0:50:AD,AR_C:6_123459_C_G/A,6_123460_C_G/A/T,6_123458_C_G/A/T::ID21:1 3/3:50 1/0:50:AD::::0 1/1:50:AR,AD:::ID21:1 0/0:50 +6 123459 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD:::ID21,ID22:1 0/1:50:AD,AR_C:6_123457_C_G/A,6_123459_C_G/A/T,6_123460_C_G/A/T,6_123458_C_G/A/T::ID21,ID22:1 0/1:50:AD,AR_C:6_123457_C_G/A,6_123460_C_G/A/T,6_123458_C_G/A/T::ID21,ID22:1 1/0:50:AD:::ID22:1 0/2:50 2/2:50 +6 123460 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T::ID21:1 1/2:50:AR,AD,AR_C:6_123457_C_G/A,6_123459_C_G/A/T,6_123459_C_G/A,6_123458_C_G/A/T::ID21:1 0/3:50 2/0:50 2/0:50 0/0:50 +6 123461 . C G,A . PASS CSQ=P|1|G|GENE4|EntrezGene|ID21|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD:::ID21:1 2/0:50 1/0:50:AD:::ID21:1 2/2:50 1/0:50:AD:::ID21:1 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50:XLD::::0 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50:XLD 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::::0 0/1:50:XLD::::0 0/1:50:XLD::::0 1/0:50:XLD::::0 1/0:50:XLD::::0 0/0:50 diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index f11c574..b81c6b7 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -55,6 +55,12 @@ 5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::1:ID2a 0/0:50 0/0:50 1/0:50:AD_IP:::ID2a:1 0/0:50 1/0:50 5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD::::0 ./.:50 0/0:50 1/0:50:AD::::0 1/0:50 0/0:50 5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AD_IP::0::0 1/1:50 0/1:50 1/0:50:AD::::0 1/1:50 0/0:50 +6 123457 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T:1:ID21,ID22 2/0:50 2/0:50 1/0:50:AD_IP:::ID22:1 0/0:50 1/0:50 +6 123458 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD,AR_C:6_123459_C_G/A/T::ID21 2/.:50 3/0:50 1/0:50:AD::::0 1/0:50 0/0:50 +6 123459 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/3:50:AD,AR_C:6_123457_C_G/A,6_123460_C_G/A/T,6_123458_C_G/A/T:0:ID21 1/0:50 3/3:50 1/0:50:AD::::0 1/1:50 0/0:50 +6 123459 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:AR,AD_IP::0:ID21,ID22:1 0/1:50 0/1:50 1/0:50:AD:::ID22 0/2:50 2/2:50 +6 123460 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP,AR_C:6_123459_C_G/A/T:0:ID21:1 1/2:50 0/3:50 2/0:50 2/0:50 0/0:50 +6 123461 . C G,A . PASS CSQ=P|1|G|GENE4|EntrezGene|ID21|1|AD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:AD_IP::0:ID21:1 2/0:50 1/0:50 2/2:50 1/0:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD::1::0 0/0:50 0/0:50 1/0:50:XLD::::0 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP:VI:VIC:VID:VIG:VIM 1/0:50:XLD ./.:50 0/0:50 1/0:50:XLD 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP:VI:VIC:VID:VIG:VIM 1/1:50:XLD,XLR::0::0 0/1:50 0/1:50 1/0:50:XLD::::0 1/0:50 0/0:50 diff --git a/src/test/resources/integration.vcf b/src/test/resources/integration.vcf index 09ef286..36cfdd7 100644 --- a/src/test/resources/integration.vcf +++ b/src/test/resources/integration.vcf @@ -50,10 +50,16 @@ 5 123457 . C G . PASS CSQ=B|1|G|GENE1|EntrezGene|ID1a|1|AR,P|1|G|GENE2|EntrezGene|ID2a||AD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 5 123458 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 5 123459 . C G . PASS CSQ=B|1|G|GENE3|EntrezGene|ID3a|1|AR GT:DP 1/1:50 1/1:50 0/1:50 1/0:50 1/1:50 0/0:50 +6 123457 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP 1/0:50 2/0:50 2/0:50 1/0:50 0/0:50 1/0:50 +6 123458 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP 1/0:50 2/.:50 3/0:50 1/0:50 1/0:50 0/0:50 +6 123459 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP 1/3:50 1/0:50 3/3:50 1/0:50 1/1:50 0/0:50 +6 123459 . C G,A . PASS CSQ=P|1|G|GENE1|EntrezGene|ID21|1|AR,P|1|G|GENE2|EntrezGene|ID22||AD GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 0/2:50 2/2:50 +6 123460 . C G,A,T . PASS CSQ=P|1|G|GENE3|EntrezGene|ID21|1|AR GT:DP 1/0:50 1/2:50 0/3:50 2/0:50 2/0:50 0/0:50 +6 123461 . C G,A . PASS CSQ=P|1|G|GENE4|EntrezGene|ID21|1|AD GT:DP 1/0:50 2/0:50 1/0:50 2/2:50 1/0:50 0/0:50 X 123457 . C G . PASS CSQ=P|1|G|GENE5|EntrezGene|ID5||XLR,P|1|G|GENE7|EntrezGene|ID7||XLD GT:DP 1/0:50 0/0:50 0/0:50 1/0:50 0/0:50 1/0:50 X 123458 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 1/0:50 0/0:50 X 123459 . C G . PASS CSQ=P|1|G|GENE6|EntrezGene|ID6||XLR GT:DP 1/1:50 0/1:50 0/1:50 1/0:50 1/0:50 0/0:50 Y 123457 . C G . PASS CSQ=P|1|G|GENE9|EntrezGene|ID9|| GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 ./.:50 0/0:50 Y 123458 . C G . PASS CSQ=P|1|G|GENE10|EntrezGene|ID10||YL GT:DP 1/0:50 ./.:50 0/0:50 1/0:50 ./.:50 0/0:50 Y 123459 . C G . PASS CSQ=P|1|G|GENE11|EntrezGene|ID11||YL GT:DP 1:50 .:50 0:50 1:50 .:50 0:50 -MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP 1:50 .:50 0:50 1:50 .:50 0:50 \ No newline at end of file +MT 123459 . C G . PASS CSQ=P|1|G|GENE12|EntrezGene|ID12|| GT:DP 1:50 .:50 0:50 1:50 .:50 0:50 From 47dceff52418d02db7fa1ae1f3ae4809b6b2646d Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 25 Sep 2024 12:59:30 +0200 Subject: [PATCH 15/28] Refactor: package structure --- .../vcf/inheritance/matcher/Annotator.java | 30 ++++---- .../matcher/AppRunnerFactoryImpl.java | 4 ++ .../inheritance/matcher/AppRunnerImpl.java | 2 + .../matcher/EffectiveGenotype.java | 72 ------------------- .../matcher/InheritanceService.java | 53 +++++++------- .../matcher/PedigreeInheritanceChecker.java | 17 ++--- .../inheritance/matcher/VcfRecordFactory.java | 9 --- .../matcher/checker/AdChecker.java | 20 +++--- .../checker/AdNonPenetranceChecker.java | 16 ++--- .../matcher/checker/ArChecker.java | 20 +++--- .../matcher/checker/ArCompoundChecker.java | 64 ++++++++--------- .../matcher/checker/DeNovoChecker.java | 34 ++++----- .../matcher/checker/DominantChecker.java | 20 +++--- .../matcher/checker/InheritanceChecker.java | 16 ++--- .../matcher/checker/MtChecker.java | 20 +++--- .../matcher/checker/XldChecker.java | 20 +++--- .../matcher/checker/XlrChecker.java | 20 +++--- .../matcher/checker/YlChecker.java | 20 +++--- .../matcher/model/CompoundCheckResult.java | 4 +- .../matcher/util/InheritanceUtils.java | 4 +- .../vcf/inheritance/matcher/vcf/Genotype.java | 72 +++++++++++++++++++ .../matcher/{ => vcf}/RecordWriter.java | 2 +- .../{ => vcf}/RecordWriterFactory.java | 2 +- .../{ => vcf}/RecordWriterFactoryImpl.java | 2 +- .../matcher/{ => vcf}/RecordWriterImpl.java | 2 +- .../{ => vcf}/VariantContextUtils.java | 19 ++--- .../matcher/{ => vcf}/VcfReader.java | 4 +- .../matcher/{ => vcf}/VcfReaderFactory.java | 2 +- .../{ => vcf}/VcfReaderFactoryImpl.java | 3 +- .../VcfRecord.java} | 12 ++-- .../matcher/vcf/VcfRecordFactory.java | 9 +++ .../{ => vcf}/VcfRecordFactoryImpl.java | 7 +- .../{ => vcf/meta}/MissingInfoException.java | 2 +- .../meta}/MissingVepAnnotationException.java | 2 +- .../matcher/{ => vcf/meta}/VepMetadata.java | 2 +- .../matcher/MissingInfoExceptionTest.java | 1 + .../MissingVepAnnotationExceptionTest.java | 1 + .../PedigreeInheritanceCheckerTest.java | 43 +++++------ .../matcher/VariantContextUtilsTest.java | 4 +- .../matcher/checker/AdCheckerTest.java | 6 +- .../matcher/checker/AdNonPenCheckerTest.java | 8 +-- .../matcher/checker/ArCheckerTest.java | 6 +- .../checker/ArCompoundCheckerTest.java | 6 +- .../matcher/checker/DeNovoCheckerTest.java | 10 +-- .../matcher/checker/MtCheckerTest.java | 6 +- .../matcher/checker/XldCheckerTest.java | 6 +- .../matcher/checker/XlrCheckerTest.java | 6 +- .../matcher/checker/YlCheckerTest.java | 6 +- .../matcher/util/VariantContextTestUtil.java | 8 +-- 49 files changed, 370 insertions(+), 354 deletions(-) delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java delete mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/Genotype.java rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/RecordWriter.java (82%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/RecordWriterFactory.java (74%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/RecordWriterFactoryImpl.java (96%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/RecordWriterImpl.java (93%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/VariantContextUtils.java (56%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/VcfReader.java (92%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/VcfReaderFactory.java (73%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/VcfReaderFactoryImpl.java (90%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{VariantRecord.java => vcf/VcfRecord.java} (67%) create mode 100644 src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactory.java rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf}/VcfRecordFactoryImpl.java (93%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf/meta}/MissingInfoException.java (84%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf/meta}/MissingVepAnnotationException.java (85%) rename src/main/java/org/molgenis/vcf/inheritance/matcher/{ => vcf/meta}/VepMetadata.java (97%) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 1d3f2b9..142e3c4 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -17,6 +17,8 @@ import java.util.stream.Collectors; import org.molgenis.vcf.inheritance.matcher.model.*; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.utils.UnexpectedEnumException; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -51,31 +53,31 @@ VCFHeader annotateHeader(VCFHeader vcfHeader) { return vcfHeader; } - VariantContext annotateInheritance(VariantRecord variantRecord, Collection pedigrees, Map inheritanceResultMap, List probands) { - GenotypesContext genotypesContext = GenotypesContext.copy(variantRecord.variantContext().getGenotypes()); - VariantContextBuilder variantContextBuilder = new VariantContextBuilder(variantRecord.variantContext()); + VariantContext annotateInheritance(VcfRecord vcfRecord, Collection pedigrees, Map inheritanceResultMap, List probands) { + GenotypesContext genotypesContext = GenotypesContext.copy(vcfRecord.variantContext().getGenotypes()); + VariantContextBuilder variantContextBuilder = new VariantContextBuilder(vcfRecord.variantContext()); for (Pedigree pedigree : pedigrees) { pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(sample -> { - EffectiveGenotype effectiveGenotype = variantRecord.getGenotype(sample.getPerson().getIndividualId()); - Genotype genotype = effectiveGenotype != null ? effectiveGenotype.unwrap() : null; + Genotype effectiveGenotype = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); + htsjdk.variant.variantcontext.Genotype genotype = effectiveGenotype != null ? effectiveGenotype.unwrap() : null; if (inheritanceResultMap.containsKey(pedigree) && genotype != null) { - genotypesContext.replace(annotateGenotype(inheritanceResultMap.get(pedigree), genotype, sample, variantRecord)); + genotypesContext.replace(annotateGenotype(inheritanceResultMap.get(pedigree), genotype, sample, vcfRecord)); } }); } return variantContextBuilder.genotypes(genotypesContext).make(); } - private Genotype annotateGenotype(InheritanceResult inheritanceResult, Genotype genotype, Sample sample, VariantRecord variantRecord) { + private htsjdk.variant.variantcontext.Genotype annotateGenotype(InheritanceResult inheritanceResult, htsjdk.variant.variantcontext.Genotype genotype, Sample sample, VcfRecord vcfRecord) { GenotypeBuilder genotypeBuilder = new GenotypeBuilder(genotype); Set vig = new HashSet<>(); Set compounds = getCompoundStrings(inheritanceResult.getCompounds()); String vic = inheritanceResult.getCompounds().isEmpty() ? "" : String.join(",", compounds); - MatchEnum match = getMatch(inheritanceResult, variantRecord); + MatchEnum match = getMatch(inheritanceResult, vcfRecord); Set vi = mapInheritanceModes(inheritanceResult); String vim = mapInheritanceMatch(match); if ((match == TRUE || match == POTENTIAL)) { - vig = getMatchingGenes(inheritanceResult.getPedigreeInheritanceMatches(), variantRecord.geneInfos(), inheritanceResult.getCompounds()); + vig = getMatchingGenes(inheritanceResult.getPedigreeInheritanceMatches(), vcfRecord.geneInfos(), inheritanceResult.getCompounds()); } genotypeBuilder.attribute(INHERITANCE_MODES, String.join(",", vi)); @@ -134,8 +136,8 @@ private Set mapInheritanceModes(InheritanceResult inheritanceResult) { } private String createKey(CompoundCheckResult result) { - VariantRecord variantRecord = result.getPossibleCompound(); - return String.format("%s_%s_%s_%s", variantRecord.getContig(), variantRecord.getStart(), variantRecord.getReference().getBaseString(), variantRecord.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); + VcfRecord vcfRecord = result.getPossibleCompound(); + return String.format("%s_%s_%s_%s", vcfRecord.getContig(), vcfRecord.getStart(), vcfRecord.getReference().getBaseString(), vcfRecord.getAlternateAlleles().stream().map(Allele::getBaseString).collect(Collectors.joining("/"))); } /** @@ -145,16 +147,16 @@ private String createKey(CompoundCheckResult result) { * - inheritance match is unknown ifa gene has unknown inheritance pattern. * - inheritance match is false if a gene has known (but mismatching) inheritance pattern. */ - public MatchEnum getMatch(InheritanceResult inheritanceResult, VariantRecord variantRecord) { + public MatchEnum getMatch(InheritanceResult inheritanceResult, VcfRecord vcfRecord) { //If no inheritance pattern is suitable for the sample, regardless of the gene: inheritance match is false. Set pedigreeInheritanceMatches = inheritanceResult.getPedigreeInheritanceMatches(); if (pedigreeInheritanceMatches.isEmpty()) { return FALSE; } - boolean containsUnknownGene = variantRecord.geneInfos().isEmpty() || variantRecord.geneInfos().stream().anyMatch(geneInfo -> geneInfo.inheritanceModes().isEmpty()); + boolean containsUnknownGene = vcfRecord.geneInfos().isEmpty() || vcfRecord.geneInfos().stream().anyMatch(geneInfo -> geneInfo.inheritanceModes().isEmpty()); Set result = new HashSet<>(); - for (GeneInfo geneInfo : variantRecord.geneInfos()) { + for (GeneInfo geneInfo : vcfRecord.geneInfos()) { if (geneInfo.inheritanceModes().stream() .anyMatch(geneInheritanceMode -> isMatch(pedigreeInheritanceMatches, geneInheritanceMode))) { if (pedigreeInheritanceMatches.stream().anyMatch(pedigreeInheritanceMatch -> !pedigreeInheritanceMatch.isUncertain())) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java index fcf3302..9696159 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerFactoryImpl.java @@ -2,6 +2,10 @@ import org.molgenis.vcf.inheritance.matcher.model.Settings; import org.molgenis.vcf.inheritance.matcher.util.InheritanceServiceFactory; +import org.molgenis.vcf.inheritance.matcher.vcf.RecordWriter; +import org.molgenis.vcf.inheritance.matcher.vcf.RecordWriterFactory; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfReader; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfReaderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java index 4e1d13b..3c5a999 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppRunnerImpl.java @@ -1,5 +1,7 @@ package org.molgenis.vcf.inheritance.matcher; +import org.molgenis.vcf.inheritance.matcher.vcf.RecordWriter; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java deleted file mode 100644 index 6ecff48..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/EffectiveGenotype.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import htsjdk.variant.variantcontext.Allele; - -import java.util.List; - -import static java.util.Objects.requireNonNull; - -public class EffectiveGenotype { - final htsjdk.variant.variantcontext.Genotype genotype; - - public EffectiveGenotype(htsjdk.variant.variantcontext.Genotype originalGenotype) { - this.genotype = requireNonNull(originalGenotype); - } - - public htsjdk.variant.variantcontext.Genotype unwrap() { - return genotype; - } - - //combination of no_call/call or fully called gt with single VUS allele - public boolean isMixed() { - return genotype.isMixed() || (!genotype.isHom()); - } - - public int getPloidy() { - return genotype.getPloidy(); - } - - public boolean isCalled() { - return genotype.isCalled(); - } - - public List getAlleles() { - return genotype.getAlleles(); - } - - public boolean isPhased() { - return genotype.isPhased(); - } - - public Allele getAllele(int i) { - return genotype.getAllele(i); - } - - public boolean isHomRef() { - return genotype.isHomRef(); - } - - public boolean isNoCall() { - return genotype.isNoCall(); - } - - public boolean hasMissingAllele() { - return genotype.getAlleles().stream().anyMatch(Allele::isNoCall); - } - - public boolean hasReference() { - return genotype.getAlleles().stream().anyMatch(Allele::isReference); - } - - public boolean hasAltAllele() { - return genotype.hasAltAllele(); - } - - public boolean isHom() { - return genotype.isHom(); - } - - public boolean isHet() { - return genotype.isHet(); - } -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java index a7926dc..77555d0 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/InheritanceService.java @@ -6,6 +6,9 @@ import org.molgenis.vcf.inheritance.matcher.checker.ArCompoundChecker; import org.molgenis.vcf.inheritance.matcher.checker.DeNovoChecker; import org.molgenis.vcf.inheritance.matcher.model.*; +import org.molgenis.vcf.inheritance.matcher.vcf.RecordWriter; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfReader; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.utils.sample.model.*; import java.nio.file.Path; @@ -13,7 +16,7 @@ import static java.util.Collections.singletonMap; import static java.util.Objects.requireNonNull; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.getAltAlleles; +import static org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils.getAltAlleles; import static org.molgenis.vcf.inheritance.matcher.model.InheritanceMode.*; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.FALSE; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.POTENTIAL; @@ -47,63 +50,63 @@ public void run(VcfReader vcfReader, RecordWriter recordWriter) { VCFHeader newHeader = annotator.annotateHeader(vcfReader.getFileHeader()); recordWriter.writeHeader(newHeader); - Map> vcfRecordGeneInfoMap = new HashMap<>(); - List variantRecords = vcfReader.stream().toList(); + Map> vcfRecordGeneInfoMap = new HashMap<>(); + List vcfRecords = vcfReader.stream().toList(); - for (VariantRecord variantRecord : variantRecords) { + for (VcfRecord vcfRecord : vcfRecords) { //Only perform matching if a pathogenic or vus allele is present - if (!variantRecord.pathogenicAlleles().isEmpty()) { - addToVcfRecordMap(variantRecord, vcfRecordGeneInfoMap); + if (!vcfRecord.pathogenicAlleles().isEmpty()) { + addToVcfRecordMap(vcfRecord, vcfRecordGeneInfoMap); } } - for (VariantRecord variantRecord : variantRecords) { - matchVariantRecord(recordWriter, variantRecord, pedigrees, vcfRecordGeneInfoMap); + for (VcfRecord vcfRecord : vcfRecords) { + matchVcfRecord(recordWriter, vcfRecord, pedigrees, vcfRecordGeneInfoMap); } } - private void matchVariantRecord(RecordWriter recordWriter, VariantRecord variantRecord, Collection pedigrees, Map> vcfRecordGeneInfoMap) { + private void matchVcfRecord(RecordWriter recordWriter, VcfRecord vcfRecord, Collection pedigrees, Map> vcfRecordGeneInfoMap) { Map inheritanceResultMap = new HashMap<>(); - matchPedigree(variantRecord, pedigrees, vcfRecordGeneInfoMap, inheritanceResultMap); + matchPedigree(vcfRecord, pedigrees, vcfRecordGeneInfoMap, inheritanceResultMap); - VariantContext annotatedVc = annotator.annotateInheritance(variantRecord, pedigrees, inheritanceResultMap, probands); + VariantContext annotatedVc = annotator.annotateInheritance(vcfRecord, pedigrees, inheritanceResultMap, probands); recordWriter.add(annotatedVc); } - private void matchPedigree(VariantRecord variantRecord, Collection pedigrees, Map> vcfRecordGeneInfoMap, Map inheritanceResultMap) { + private void matchPedigree(VcfRecord vcfRecord, Collection pedigrees, Map> vcfRecordGeneInfoMap, Map inheritanceResultMap) { for (Pedigree pedigree : pedigrees) { InheritanceResult inheritanceResult = InheritanceResult.builder().build(); - Set altAllelesForPedigree = getAltAlleles(variantRecord, pedigree); + Set altAllelesForPedigree = getAltAlleles(vcfRecord, pedigree); //Only perform matching if a family member with a pathogenic allele is present - if (altAllelesForPedigree.stream().anyMatch(allele -> variantRecord.pathogenicAlleles().contains(allele))) { - addToVcfRecordMap(variantRecord, vcfRecordGeneInfoMap); + if (altAllelesForPedigree.stream().anyMatch(allele -> vcfRecord.pathogenicAlleles().contains(allele))) { + addToVcfRecordMap(vcfRecord, vcfRecordGeneInfoMap); Set modes = Set.of(AD, AR, XLD, XLR, MT, YL); modes.forEach(mode -> { - MatchEnum isMatch = pedigreeInheritanceChecker.check(variantRecord, pedigree, mode); + MatchEnum isMatch = pedigreeInheritanceChecker.check(vcfRecord, pedigree, mode); if (isMatch != FALSE) { inheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(mode, isMatch == POTENTIAL)); } }); if (inheritanceResult.getPedigreeInheritanceMatches().stream().noneMatch(match -> match.inheritanceMode() == AD)) { - MatchEnum isAdIpMatch = pedigreeInheritanceChecker.check(variantRecord, pedigree, AD_IP); + MatchEnum isAdIpMatch = pedigreeInheritanceChecker.check(vcfRecord, pedigree, AD_IP); if (isAdIpMatch != FALSE) { inheritanceResult.addInheritanceMode(new PedigreeInheritanceMatch(AD_IP, isAdIpMatch == POTENTIAL)); } } - matchCompounds(variantRecord, vcfRecordGeneInfoMap, pedigree, inheritanceResult); + matchCompounds(vcfRecord, vcfRecordGeneInfoMap, pedigree, inheritanceResult); Map denovoResult = new HashMap<>(); pedigree.getMembers().values().stream().filter(sample -> probands.isEmpty() || probands.contains(sample.getPerson().getIndividualId())).forEach(proband -> - denovoResult.put(proband, deNovoChecker.checkDeNovo(variantRecord, proband))); + denovoResult.put(proband, deNovoChecker.checkDeNovo(vcfRecord, proband))); inheritanceResult.setDenovo(denovoResult); inheritanceResultMap.put(pedigree, inheritanceResult); } } } - private void matchCompounds(VariantRecord variantRecord, Map> vcfRecordGeneInfoMap, Pedigree pedigree, InheritanceResult inheritanceResult) { - Map> compoundsMap = arCompoundChecker.check(vcfRecordGeneInfoMap, variantRecord, pedigree); + private void matchCompounds(VcfRecord vcfRecord, Map> vcfRecordGeneInfoMap, Pedigree pedigree, InheritanceResult inheritanceResult) { + Map> compoundsMap = arCompoundChecker.check(vcfRecordGeneInfoMap, vcfRecord, pedigree); if (!isEmpty(compoundsMap)) { inheritanceResult.setCompounds(compoundsMap); boolean isCertain = false; @@ -126,10 +129,10 @@ private boolean isEmpty(Map> compounds) { return true; } - private void addToVcfRecordMap(VariantRecord variantRecord, Map> vcfRecordGeneInfoMap) { - for (GeneInfo geneInfo : variantRecord.geneInfos()) { - Set records = vcfRecordGeneInfoMap.containsKey(geneInfo) ? vcfRecordGeneInfoMap.get(geneInfo) : new HashSet<>(); - records.add(variantRecord); + private void addToVcfRecordMap(VcfRecord vcfRecord, Map> vcfRecordGeneInfoMap) { + for (GeneInfo geneInfo : vcfRecord.geneInfos()) { + Set records = vcfRecordGeneInfoMap.containsKey(geneInfo) ? vcfRecordGeneInfoMap.get(geneInfo) : new HashSet<>(); + records.add(vcfRecord); vcfRecordGeneInfoMap.put(geneInfo, records); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java index 709681a..c5f1236 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceChecker.java @@ -2,6 +2,7 @@ import org.molgenis.vcf.inheritance.matcher.checker.*; import org.molgenis.vcf.inheritance.matcher.model.*; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.utils.UnexpectedEnumException; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.springframework.stereotype.Component; @@ -27,16 +28,16 @@ public PedigreeInheritanceChecker(XldChecker xldChecker, XlrChecker xlrChecker, this.ylChecker = ylChecker; } - MatchEnum check(VariantRecord variantRecord, Pedigree pedigree, InheritanceMode mode) { + MatchEnum check(VcfRecord vcfRecord, Pedigree pedigree, InheritanceMode mode) { MatchEnum result; switch(mode){ - case AD -> result = adChecker.check(variantRecord, pedigree); - case AD_IP -> result = adNonPenetranceChecker.check(variantRecord, pedigree); - case AR -> result = arChecker.check(variantRecord, pedigree); - case XLR -> result = xlrChecker.check(variantRecord, pedigree); - case XLD -> result = xldChecker.check(variantRecord, pedigree); - case MT -> result = mtChecker.check(variantRecord, pedigree); - case YL -> result = ylChecker.check(variantRecord, pedigree); + case AD -> result = adChecker.check(vcfRecord, pedigree); + case AD_IP -> result = adNonPenetranceChecker.check(vcfRecord, pedigree); + case AR -> result = arChecker.check(vcfRecord, pedigree); + case XLR -> result = xlrChecker.check(vcfRecord, pedigree); + case XLD -> result = xldChecker.check(vcfRecord, pedigree); + case MT -> result = mtChecker.check(vcfRecord, pedigree); + case YL -> result = ylChecker.check(vcfRecord, pedigree); default -> throw new UnexpectedEnumException(mode); } return result; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java deleted file mode 100644 index 2bbc9ad..0000000 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.molgenis.vcf.inheritance.matcher; - -import htsjdk.variant.variantcontext.VariantContext; - -import java.util.Set; - -public interface VcfRecordFactory { - VariantRecord create(VariantContext variantContext, Set pathogenicClasses); -} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java index d1cec83..942522a 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdChecker.java @@ -1,8 +1,8 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -23,18 +23,18 @@ public class AdChecker extends DominantChecker { * Check whether the AD inheritance pattern could match for a variant in a pedigree */ public MatchEnum check( - VariantRecord variantRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantRecord)) { + VcfRecord vcfRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(vcfRecord)) { return FALSE; } - return checkFamily(variantRecord, family); + return checkFamily(vcfRecord, family); } - public MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if(genotype == null){ matches.add(POTENTIAL); } @@ -48,10 +48,10 @@ else if(genotype.isHomRef()){ return merge(matches); } - public MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); if (genotype != null && genotype.isHomRef()) { return FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java index 88538c0..b6fb1b6 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenetranceChecker.java @@ -2,9 +2,9 @@ import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Pedigree; import org.molgenis.vcf.utils.sample.model.Sample; @@ -17,20 +17,20 @@ public class AdNonPenetranceChecker { public MatchEnum check( - VariantRecord variantRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantRecord)) { + VcfRecord vcfRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(vcfRecord)) { return FALSE; } Set results = new HashSet<>(); for (Sample sample : family.getMembers().values()) { - results.add(checkSample(sample, variantRecord)); + results.add(checkSample(sample, vcfRecord)); } return CheckerUtils.merge(results); } - MatchEnum checkSample(Sample sample, VariantRecord variantRecord) { - EffectiveGenotype sampleGt = variantRecord.getGenotype(sample.getPerson().getIndividualId()); + MatchEnum checkSample(Sample sample, VcfRecord vcfRecord) { + Genotype sampleGt = vcfRecord.getGenotype(sample.getPerson().getIndividualId()); switch (sample.getPerson().getAffectedStatus()) { case AFFECTED -> { if (sampleGt != null && sampleGt.isHomRef()) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java index ed7b856..6b5da5e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArChecker.java @@ -4,9 +4,9 @@ import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -19,18 +19,18 @@ public class ArChecker extends InheritanceChecker { public MatchEnum check( - VariantRecord variantRecord, Pedigree family) { - if (!VariantContextUtils.onAutosome(variantRecord)) { + VcfRecord vcfRecord, Pedigree family) { + if (!VariantContextUtils.onAutosome(vcfRecord)) { return FALSE; } - return checkFamily(variantRecord, family); + return checkFamily(vcfRecord, family); } - protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if(genotype == null){ matches.add(POTENTIAL); } else if (genotype.hasReference()) { @@ -45,10 +45,10 @@ protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); if (genotype!= null && genotype.hasReference()) { return FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java index 9f9de41..bfb944c 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundChecker.java @@ -1,6 +1,6 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onAutosome; +import static org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils.onAutosome; import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.getMembersByStatus; import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; @@ -9,8 +9,8 @@ import java.util.*; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.CompoundCheckResult; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -21,26 +21,26 @@ public class ArCompoundChecker { public Map> check( - Map> geneVariantMap, - VariantRecord variantRecord, Pedigree family) { - if (onAutosome(variantRecord)) { + Map> geneVariantMap, + VcfRecord vcfRecord, Pedigree family) { + if (onAutosome(vcfRecord)) { Map> compounds = new HashMap<>(); - for (GeneInfo geneInfo : variantRecord.geneInfos()) { - checkForGene(geneVariantMap, variantRecord, family, compounds, geneInfo); + for (GeneInfo geneInfo : vcfRecord.geneInfos()) { + checkForGene(geneVariantMap, vcfRecord, family, compounds, geneInfo); } return compounds; } return Collections.emptyMap(); } - private void checkForGene(Map> geneVariantMap, - VariantRecord variantRecord, Pedigree family, Map> compoundsMap, GeneInfo geneInfo) { - Collection variantGeneRecords = geneVariantMap.get(geneInfo); + private void checkForGene(Map> geneVariantMap, + VcfRecord vcfRecord, Pedigree family, Map> compoundsMap, GeneInfo geneInfo) { + Collection variantGeneRecords = geneVariantMap.get(geneInfo); Set compounds = new HashSet<>(); if (variantGeneRecords != null) { - for (VariantRecord otherRecord : variantGeneRecords) { - if (!otherRecord.equals(variantRecord)) { - MatchEnum isPossibleCompound = checkFamily(family, variantRecord, otherRecord); + for (VcfRecord otherRecord : variantGeneRecords) { + if (!otherRecord.equals(vcfRecord)) { + MatchEnum isPossibleCompound = checkFamily(family, vcfRecord, otherRecord); if (isPossibleCompound != FALSE) { CompoundCheckResult result = CompoundCheckResult.builder().possibleCompound(otherRecord).isCertain(isPossibleCompound != POTENTIAL).build(); compounds.add(result); @@ -51,31 +51,31 @@ private void checkForGene(Map> geneVariantMap, compoundsMap.put(geneInfo, compounds); } - private MatchEnum checkFamily(Pedigree family, VariantRecord variantRecord, - VariantRecord otherVariantGeneRecord) { + private MatchEnum checkFamily(Pedigree family, VcfRecord vcfRecord, + VcfRecord otherVariantGeneRecord) { Map> membersByStatus = getMembersByStatus(family); Set> affectedGenotypes = new HashSet<>(); Set> otherAffectedGenotypes = new HashSet<>(); Set matches = new HashSet<>(); - matches.add(checkAffected(variantRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); - matches.add(checkUnaffected(variantRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); + matches.add(checkAffected(vcfRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); + matches.add(checkUnaffected(vcfRecord, otherVariantGeneRecord, membersByStatus, affectedGenotypes, otherAffectedGenotypes)); if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { matches.add(POTENTIAL); } return merge(matches); } - private MatchEnum checkUnaffected(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { + private MatchEnum checkUnaffected(VcfRecord vcfRecord, VcfRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - matches.add(checkUnaffectedSample(variantRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, unAffectedSample)); + matches.add(checkUnaffectedSample(vcfRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, unAffectedSample)); } return merge(matches); } - private static MatchEnum checkUnaffectedSample(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample unAffectedSample) { + private static MatchEnum checkUnaffectedSample(VcfRecord vcfRecord, VcfRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample unAffectedSample) { Set matches = new HashSet<>(); - matches.add(checkSingleUnaffectedSampleVariant(variantRecord, affectedGenotypes, unAffectedSample)); + matches.add(checkSingleUnaffectedSampleVariant(vcfRecord, affectedGenotypes, unAffectedSample)); matches.add(checkSingleUnaffectedSampleVariant(otherVariantGeneRecord, otherAffectedGenotypes, unAffectedSample)); if (matches.contains(TRUE)) { return TRUE; @@ -83,8 +83,8 @@ private static MatchEnum checkUnaffectedSample(VariantRecord variantRecord, Vari return POTENTIAL; } - EffectiveGenotype sampleGt = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); - EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype sampleGt = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype sampleOtherGt = otherVariantGeneRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if ((sampleGt != null && sampleOtherGt != null) && (sampleGt.isPhased() && sampleOtherGt.isPhased() && (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || @@ -94,9 +94,9 @@ private static MatchEnum checkUnaffectedSample(VariantRecord variantRecord, Vari return FALSE; } - private static MatchEnum checkSingleUnaffectedSampleVariant(VariantRecord variantRecord, Set> affectedGenotypes, Sample unAffectedSample) { + private static MatchEnum checkSingleUnaffectedSampleVariant(VcfRecord vcfRecord, Set> affectedGenotypes, Sample unAffectedSample) { Set matches = new HashSet<>(); - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); for (List affectedGenotype : affectedGenotypes) { if (genotype != null && genotype.isHomRef()) { matches.add(TRUE); @@ -110,17 +110,17 @@ private static MatchEnum checkSingleUnaffectedSampleVariant(VariantRecord varian return merge(matches); } - private MatchEnum checkAffected(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { + private MatchEnum checkAffected(VcfRecord vcfRecord, VcfRecord otherVariantGeneRecord, Map> membersByStatus, Set> affectedGenotypes, Set> otherAffectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - checkAffectedSample(variantRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, affectedSample, matches); + checkAffectedSample(vcfRecord, otherVariantGeneRecord, affectedGenotypes, otherAffectedGenotypes, affectedSample, matches); } return merge(matches); } - private static void checkAffectedSample(VariantRecord variantRecord, VariantRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample affectedSample, Set matches) { - EffectiveGenotype sampleGt = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); - EffectiveGenotype sampleOtherGt = otherVariantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + private static void checkAffectedSample(VcfRecord vcfRecord, VcfRecord otherVariantGeneRecord, Set> affectedGenotypes, Set> otherAffectedGenotypes, Sample affectedSample, Set matches) { + Genotype sampleGt = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype sampleOtherGt = otherVariantGeneRecord.getGenotype(affectedSample.getPerson().getIndividualId()); if (sampleGt != null) { affectedGenotypes.add(sampleGt.getAlleles()); } @@ -139,7 +139,7 @@ private static void checkAffectedSample(VariantRecord variantRecord, VariantReco } } - private static boolean checkAffectedPhased(EffectiveGenotype sampleGt, EffectiveGenotype sampleOtherGt) { + private static boolean checkAffectedPhased(Genotype sampleGt, Genotype sampleOtherGt) { return sampleGt.isPhased() && sampleOtherGt.isPhased() && (sampleGt.getAllele(0).isReference() && sampleOtherGt.getAllele(0).isReference()) || (sampleGt.getAllele(1).isReference() && sampleOtherGt.getAllele(1).isReference()); diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java index ef68ef8..18f23ce 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoChecker.java @@ -6,8 +6,8 @@ import htsjdk.variant.variantcontext.Allele; import org.molgenis.vcf.inheritance.matcher.ContigUtils; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.Sample; import org.molgenis.vcf.utils.sample.model.Sex; @@ -21,16 +21,16 @@ public class DeNovoChecker { //use original GT instead of inheritance matcher specific one since we are looking for "new alleles" not specifically pathogenic ones - public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { - EffectiveGenotype probandGt = variantRecord.getGenotype(proband.getPerson().getIndividualId()); - EffectiveGenotype fatherGt = variantRecord.getGenotype(proband.getPerson().getPaternalId()); - EffectiveGenotype motherGt = variantRecord.getGenotype(proband.getPerson().getMaternalId()); + public MatchEnum checkDeNovo(VcfRecord vcfRecord, Sample proband) { + Genotype probandGt = vcfRecord.getGenotype(proband.getPerson().getIndividualId()); + Genotype fatherGt = vcfRecord.getGenotype(proband.getPerson().getPaternalId()); + Genotype motherGt = vcfRecord.getGenotype(proband.getPerson().getMaternalId()); if (!hasParents(proband)) { return POTENTIAL; } - String contigId = variantRecord.getContig(); + String contigId = vcfRecord.getContig(); if ((contigId != null && ContigUtils.isChromosomeX(contigId)) && proband.getPerson().getSex() == Sex.MALE) { return checkMaleXVariant(probandGt, motherGt); } else if ((contigId != null && ContigUtils.isChromosomeY(contigId))) { @@ -42,7 +42,7 @@ public MatchEnum checkDeNovo(VariantRecord variantRecord, Sample proband) { } } - private static MatchEnum checkMaleXVariant(EffectiveGenotype probandGt, EffectiveGenotype motherGt) { + private static MatchEnum checkMaleXVariant(Genotype probandGt, Genotype motherGt) { if (probandGt == null || probandGt.isNoCall()) { return POTENTIAL; } else if (probandGt.hasAltAllele()) { @@ -57,7 +57,7 @@ private static MatchEnum checkMaleXVariant(EffectiveGenotype probandGt, Effectiv return probandGt.isNoCall() ? POTENTIAL : FALSE; } - private static MatchEnum checkYLinkedVariant(Sample proband, EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { + private static MatchEnum checkYLinkedVariant(Sample proband, Genotype probandGt, Genotype fatherGt) { return switch (proband.getPerson().getSex()) { case MALE -> checkYLinkedVariantMale(probandGt, fatherGt); case FEMALE -> FALSE; @@ -65,7 +65,7 @@ private static MatchEnum checkYLinkedVariant(Sample proband, EffectiveGenotype p }; } - private static MatchEnum checkYLinkedVariantMale(EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { + private static MatchEnum checkYLinkedVariantMale(Genotype probandGt, Genotype fatherGt) { if (probandGt.hasAltAllele()) { if (hasSameAltAlleles(probandGt, fatherGt)) { return FALSE; @@ -78,12 +78,12 @@ private static MatchEnum checkYLinkedVariantMale(EffectiveGenotype probandGt, Ef return FALSE; } - private static boolean hasSameAltAlleles(EffectiveGenotype probandGt, EffectiveGenotype fatherGt) { + private static boolean hasSameAltAlleles(Genotype probandGt, Genotype fatherGt) { return probandGt.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch(allele -> fatherGt.getAlleles().contains(allele)); } - private static MatchEnum checkMtVariant(EffectiveGenotype probandGt, EffectiveGenotype motherGt) { + private static MatchEnum checkMtVariant(Genotype probandGt, Genotype motherGt) { if (probandGt == null || probandGt.isNoCall()) { return POTENTIAL; } else if (probandGt.hasAltAllele()) { @@ -104,7 +104,7 @@ private static MatchEnum checkMtVariant(EffectiveGenotype probandGt, EffectiveGe return FALSE; } - private MatchEnum checkRegular(EffectiveGenotype probandGt, EffectiveGenotype fatherGt, EffectiveGenotype motherGt) { + private MatchEnum checkRegular(Genotype probandGt, Genotype fatherGt, Genotype motherGt) { Set result = new HashSet<>(); if (probandGt == null || probandGt.isNoCall()) { return POTENTIAL; @@ -120,7 +120,7 @@ private MatchEnum checkRegular(EffectiveGenotype probandGt, EffectiveGenotype fa return merge(result); } - private static MatchEnum checkAlleles(EffectiveGenotype fatherGt, EffectiveGenotype motherGt, Allele allele1, Allele allele2) { + private static MatchEnum checkAlleles(Genotype fatherGt, Genotype motherGt, Allele allele1, Allele allele2) { if(allele1.isNoCall() || allele2.isNoCall()) { return checkPartialCalls(fatherGt, motherGt, allele1, allele2); } @@ -134,7 +134,7 @@ else if ((containsAlleleOrRef(motherGt, allele1) && containsAlleleOrRef(fatherGt return TRUE; } - private static MatchEnum checkPartialCalls(EffectiveGenotype fatherGt, EffectiveGenotype motherGt, Allele allele1, Allele allele2) { + private static MatchEnum checkPartialCalls(Genotype fatherGt, Genotype motherGt, Allele allele1, Allele allele2) { if (allele1.isNoCall() && allele2.isCalled()) { if (containsAlleleOrNoCall(motherGt, allele2) || containsAlleleOrNoCall(fatherGt, allele2)) { return POTENTIAL; @@ -151,11 +151,11 @@ private static MatchEnum checkPartialCalls(EffectiveGenotype fatherGt, Effective return FALSE; } - private static boolean containsAlleleOrRef(EffectiveGenotype genotype, Allele allele) { + private static boolean containsAlleleOrRef(Genotype genotype, Allele allele) { return allele.isReference() || genotype.getAlleles().contains(allele); } - private static boolean containsAlleleOrNoCall(EffectiveGenotype genotype, Allele allele1) { + private static boolean containsAlleleOrNoCall(Genotype genotype, Allele allele1) { return containsAlleleOrRef(genotype, allele1) || containsAlleleOrRef(genotype, Allele.NO_CALL); } } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java index 0def21b..4de918f 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/DominantChecker.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -17,20 +17,20 @@ public abstract class DominantChecker { - MatchEnum checkFamily(VariantRecord variantRecord, Pedigree family) { + MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); + Set affectedGenotypes = new HashSet<>(); Set matches = new HashSet<>(); - matches.add(checkAffected(variantRecord, membersByStatus, affectedGenotypes)); - matches.add(checkUnaffected(variantRecord, membersByStatus, affectedGenotypes)); + matches.add(checkAffected(vcfRecord, membersByStatus, affectedGenotypes)); + matches.add(checkUnaffected(vcfRecord, membersByStatus, affectedGenotypes)); if(!membersByStatus.get(AffectedStatus.MISSING).isEmpty()){ matches.add(POTENTIAL); } return merge(matches); } - static void checkAffectedGenotypes(Set affectedGenotypes, Set matches, EffectiveGenotype genotype) { - for (EffectiveGenotype affectedGenotype : affectedGenotypes) { + static void checkAffectedGenotypes(Set affectedGenotypes, Set matches, Genotype genotype) { + for (Genotype affectedGenotype : affectedGenotypes) { if (affectedGenotype.hasAltAllele() && affectedGenotype.getAlleles().stream().filter(allele -> allele.isCalled() && allele.isNonReference()).allMatch( allele -> genotype.getAlleles().contains(allele))) { matches.add(FALSE); @@ -40,7 +40,7 @@ static void checkAffectedGenotypes(Set affectedGenotypes, Set } } - protected abstract MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes); - protected abstract MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java index d5c0362..0591344 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/InheritanceChecker.java @@ -1,8 +1,8 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -18,21 +18,21 @@ public abstract class InheritanceChecker { - protected MatchEnum checkFamily(VariantRecord variantRecord, Pedigree family) { + protected MatchEnum checkFamily(VcfRecord vcfRecord, Pedigree family) { Map> membersByStatus = getMembersByStatus(family); - Set affectedGenotypes = new HashSet<>(); + Set affectedGenotypes = new HashSet<>(); Set matches = new HashSet<>(); - matches.add(checkAffected(variantRecord, membersByStatus, affectedGenotypes)); + matches.add(checkAffected(vcfRecord, membersByStatus, affectedGenotypes)); Set affectedAltAlleles = new HashSet<>(); affectedGenotypes.forEach(genotype -> genotype.getAlleles().stream().filter(allele -> allele.isNonReference() && allele.isCalled()).forEach(affectedAltAlleles::add)); - matches.add(checkUnaffected(variantRecord, membersByStatus, affectedAltAlleles)); + matches.add(checkUnaffected(vcfRecord, membersByStatus, affectedAltAlleles)); if (!membersByStatus.get(AffectedStatus.MISSING).isEmpty()) { matches.add(POTENTIAL); } return merge(matches); } - protected abstract MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes); + protected abstract MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes); - protected abstract MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAltAlleles); + protected abstract MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedAltAlleles); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java index 510ba8c..2774109 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/MtChecker.java @@ -1,9 +1,9 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -20,18 +20,18 @@ @Component public class MtChecker extends InheritanceChecker { public MatchEnum check( - VariantRecord variantRecord, Pedigree family) { - if (!VariantContextUtils.onChromosomeMt(variantRecord)) { + VcfRecord vcfRecord, Pedigree family) { + if (!VariantContextUtils.onChromosomeMt(vcfRecord)) { return FALSE; } - return checkFamily(variantRecord, family); + return checkFamily(vcfRecord, family); } - protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if (genotype != null && (genotype.isHomRef() || (genotype.getPloidy() == 1 && genotype.hasReference()))) { matches.add(TRUE); } else if (genotype != null && genotype.getAlleles().stream().allMatch( @@ -45,10 +45,10 @@ protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); if (genotype != null && !genotype.hasAltAllele() && genotype.isCalled()) { return FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java index b2e7334..af224b1 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XldChecker.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.checker; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -10,24 +10,24 @@ import java.util.*; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeX; +import static org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils.onChromosomeX; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; @Component public class XldChecker extends DominantChecker { - public MatchEnum check(VariantRecord variantRecord, Pedigree family) { - if (!onChromosomeX(variantRecord)) { + public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { + if (!onChromosomeX(vcfRecord)) { return FALSE; } - return checkFamily(variantRecord, family); + return checkFamily(vcfRecord, family); } - public MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if(genotype == null){ matches.add(POTENTIAL); } @@ -41,10 +41,10 @@ else if(!genotype.hasAltAllele() && !genotype.isMixed() || (genotype.hasReferenc return merge(matches); } - public MatchEnum checkAffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + public MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); if (genotype != null && !genotype.hasAltAllele() && !genotype.isMixed()) { return FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java index 32fc643..ff8db49 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/XlrChecker.java @@ -1,8 +1,8 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -11,24 +11,24 @@ import java.util.*; -import static org.molgenis.vcf.inheritance.matcher.VariantContextUtils.onChromosomeX; +import static org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils.onChromosomeX; import static org.molgenis.vcf.inheritance.matcher.checker.CheckerUtils.merge; import static org.molgenis.vcf.inheritance.matcher.model.MatchEnum.*; @Component public class XlrChecker extends InheritanceChecker { - public MatchEnum check(VariantRecord variantRecord, Pedigree family) { - if (!onChromosomeX(variantRecord)) { + public MatchEnum check(VcfRecord vcfRecord, Pedigree family) { + if (!onChromosomeX(vcfRecord)) { return FALSE; } - return checkFamily(variantRecord, family); + return checkFamily(vcfRecord, family); } - protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if (genotype != null && genotype.hasReference()) { matches.add(TRUE); } else if (genotype != null && genotype.getAlleles().stream().allMatch( @@ -41,10 +41,10 @@ protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); affectedGenotypes.add(genotype); if (genotype != null && genotype.hasReference()) { return FALSE; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java index e92a866..a5769f8 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/checker/YlChecker.java @@ -1,9 +1,9 @@ package org.molgenis.vcf.inheritance.matcher.checker; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; -import org.molgenis.vcf.inheritance.matcher.VariantContextUtils; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; +import org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.utils.sample.model.AffectedStatus; import org.molgenis.vcf.utils.sample.model.Pedigree; @@ -22,18 +22,18 @@ @Component public class YlChecker extends InheritanceChecker { public MatchEnum check( - VariantRecord variantRecord, Pedigree family) { - if (!VariantContextUtils.onChromosomeY(variantRecord)) { + VcfRecord vcfRecord, Pedigree family) { + if (!VariantContextUtils.onChromosomeY(vcfRecord)) { return FALSE; } - return checkFamily(variantRecord, family); + return checkFamily(vcfRecord, family); } - protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedAlleles) { + protected MatchEnum checkUnaffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedAlleles) { Set matches = new HashSet<>(); for (Sample unAffectedSample : membersByStatus.get(AffectedStatus.UNAFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(unAffectedSample.getPerson().getIndividualId()); if (unAffectedSample.getPerson().getSex() != MALE) { matches.add(TRUE); } else if (genotype == null) { @@ -52,10 +52,10 @@ protected MatchEnum checkUnaffected(VariantRecord variantRecord, Map> membersByStatus, Set affectedGenotypes) { + protected MatchEnum checkAffected(VcfRecord vcfRecord, Map> membersByStatus, Set affectedGenotypes) { Set matches = new HashSet<>(); for (Sample affectedSample : membersByStatus.get(AffectedStatus.AFFECTED)) { - EffectiveGenotype genotype = variantRecord.getGenotype(affectedSample.getPerson().getIndividualId()); + Genotype genotype = vcfRecord.getGenotype(affectedSample.getPerson().getIndividualId()); if (affectedSample.getPerson().getSex() == FEMALE) { return FALSE; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java index f47dfcd..9ae3bc1 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/model/CompoundCheckResult.java @@ -1,11 +1,11 @@ package org.molgenis.vcf.inheritance.matcher.model; import lombok.Builder; import lombok.Value; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; @Value @Builder public class CompoundCheckResult { - VariantRecord possibleCompound; + VcfRecord possibleCompound; boolean isCertain; } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java index eac3e9a..44600e7 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/util/InheritanceUtils.java @@ -1,7 +1,7 @@ package org.molgenis.vcf.inheritance.matcher.util; import htsjdk.variant.variantcontext.Allele; -import org.molgenis.vcf.inheritance.matcher.EffectiveGenotype; +import org.molgenis.vcf.inheritance.matcher.vcf.Genotype; import org.molgenis.vcf.utils.sample.model.Sample; public class InheritanceUtils { @@ -13,7 +13,7 @@ public static boolean hasParents(Sample sample) { !(sample.getPerson().getPaternalId().isEmpty() || sample.getPerson().getPaternalId().equals("0")); } - public static boolean hasMissing(EffectiveGenotype genotype) { + public static boolean hasMissing(Genotype genotype) { return genotype == null || genotype.getAlleles().stream() .anyMatch(Allele::isNoCall); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/Genotype.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/Genotype.java new file mode 100644 index 0000000..25303cb --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/Genotype.java @@ -0,0 +1,72 @@ +package org.molgenis.vcf.inheritance.matcher.vcf; + +import htsjdk.variant.variantcontext.Allele; + +import java.util.List; + +import static java.util.Objects.requireNonNull; + +public class Genotype { + final htsjdk.variant.variantcontext.Genotype originalGenotype; + + public Genotype(htsjdk.variant.variantcontext.Genotype originalGenotype) { + this.originalGenotype = requireNonNull(originalGenotype); + } + + public htsjdk.variant.variantcontext.Genotype unwrap() { + return originalGenotype; + } + + //combination of no_call/call or fully called gt with single VUS allele + public boolean isMixed() { + return originalGenotype.isMixed() || (!originalGenotype.isHom()); + } + + public int getPloidy() { + return originalGenotype.getPloidy(); + } + + public boolean isCalled() { + return originalGenotype.isCalled(); + } + + public List getAlleles() { + return originalGenotype.getAlleles(); + } + + public boolean isPhased() { + return originalGenotype.isPhased(); + } + + public Allele getAllele(int i) { + return originalGenotype.getAllele(i); + } + + public boolean isHomRef() { + return originalGenotype.isHomRef(); + } + + public boolean isNoCall() { + return originalGenotype.isNoCall(); + } + + public boolean hasMissingAllele() { + return originalGenotype.getAlleles().stream().anyMatch(Allele::isNoCall); + } + + public boolean hasReference() { + return originalGenotype.getAlleles().stream().anyMatch(Allele::isReference); + } + + public boolean hasAltAllele() { + return originalGenotype.hasAltAllele(); + } + + public boolean isHom() { + return originalGenotype.isHom(); + } + + public boolean isHet() { + return originalGenotype.isHet(); + } +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriter.java similarity index 82% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriter.java index f1db54f..63817a0 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriter.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriter.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import htsjdk.variant.variantcontext.VariantContext; import htsjdk.variant.vcf.VCFHeader; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterFactory.java similarity index 74% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterFactory.java index eeca17e..403a872 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactory.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterFactory.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import org.molgenis.vcf.inheritance.matcher.model.Settings; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterFactoryImpl.java similarity index 96% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterFactoryImpl.java index f7d08a1..e71ae69 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterFactoryImpl.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import htsjdk.variant.variantcontext.writer.VariantContextWriter; import htsjdk.variant.variantcontext.writer.VariantContextWriterBuilder; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterImpl.java similarity index 93% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterImpl.java index 34c8f76..8a1073b 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/RecordWriterImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/RecordWriterImpl.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import static java.util.Objects.requireNonNull; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VariantContextUtils.java similarity index 56% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VariantContextUtils.java index 38d06dd..2e3b3d6 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtils.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VariantContextUtils.java @@ -1,6 +1,7 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import htsjdk.variant.variantcontext.Allele; +import org.molgenis.vcf.inheritance.matcher.ContigUtils; import org.molgenis.vcf.utils.sample.model.Pedigree; import java.util.HashSet; @@ -11,32 +12,32 @@ public class VariantContextUtils { private VariantContextUtils() { } - public static boolean onAutosome(VariantRecord variantGeneRecord) { + public static boolean onAutosome(VcfRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isAutosome(contigId); } - public static boolean onChromosomeX(VariantRecord variantGeneRecord) { + public static boolean onChromosomeX(VcfRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeX(contigId); } - public static boolean onChromosomeMt(VariantRecord variantGeneRecord) { + public static boolean onChromosomeMt(VcfRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeMt(contigId); } - public static boolean onChromosomeY(VariantRecord variantGeneRecord) { + public static boolean onChromosomeY(VcfRecord variantGeneRecord) { String contigId = variantGeneRecord.getContig(); return contigId != null && ContigUtils.isChromosomeY(contigId); } - public static Set getAltAlleles(VariantRecord variantGeneRecord, Pedigree pedigree){ + public static Set getAltAlleles(VcfRecord variantGeneRecord, Pedigree pedigree){ Set altAlleles = new HashSet<>(); for(String sample : pedigree.getMembers().keySet()){ - EffectiveGenotype effectiveGenotype = variantGeneRecord.getGenotype(sample); - if(effectiveGenotype != null) { - effectiveGenotype.unwrap().getAlleles().stream().filter(Allele::isNonReference).forEach(altAlleles::add); + Genotype genotype = variantGeneRecord.getGenotype(sample); + if(genotype != null) { + genotype.unwrap().getAlleles().stream().filter(Allele::isNonReference).forEach(altAlleles::add); } } return altAlleles; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReader.java similarity index 92% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReader.java index b530e0a..ad5e81c 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReader.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReader.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import static java.util.Objects.requireNonNull; @@ -26,7 +26,7 @@ public VcfReader(VCFFileReader vcfFileReader, VcfRecordFactory vcfRecordFactory, this.pathogenicClasses = pathogenicClasses; } - public Stream stream() { + public Stream stream() { return StreamSupport.stream(vcfFileReader.spliterator(), false).map(vc -> vcfRecordFactory.create(vc, pathogenicClasses)); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReaderFactory.java similarity index 73% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReaderFactory.java index 3d47257..a590f92 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactory.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReaderFactory.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import org.molgenis.vcf.inheritance.matcher.model.Settings; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReaderFactoryImpl.java similarity index 90% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReaderFactoryImpl.java index 51ef3fc..5c6e29d 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfReaderFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfReaderFactoryImpl.java @@ -1,6 +1,7 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import htsjdk.variant.vcf.VCFFileReader; +import org.molgenis.vcf.inheritance.matcher.vcf.meta.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.Settings; import org.molgenis.vcf.inheritance.matcher.util.VepMetadataServiceFactoryImpl; import org.springframework.stereotype.Component; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecord.java similarity index 67% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecord.java index 07a7210..71163fb 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VariantRecord.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecord.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.VariantContext; @@ -7,24 +7,20 @@ import java.util.List; import java.util.Set; -public record VariantRecord(VariantContext variantContext, Set pathogenicAlleles, Set geneInfos) { +public record VcfRecord(VariantContext variantContext, Set pathogenicAlleles, Set geneInfos) { - public EffectiveGenotype getGenotype(String sampleId) { + public Genotype getGenotype(String sampleId) { htsjdk.variant.variantcontext.Genotype gt = variantContext.getGenotype(sampleId); if (gt == null) { return null; } - return new EffectiveGenotype(gt); + return new Genotype(gt); } public List getAlternateAlleles() { return variantContext.getAlternateAlleles(); } - public VariantContext unwrap() { - return variantContext; - } - public String getContig() { return variantContext.getContig(); } diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactory.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactory.java new file mode 100644 index 0000000..f56dc3f --- /dev/null +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactory.java @@ -0,0 +1,9 @@ +package org.molgenis.vcf.inheritance.matcher.vcf; + +import htsjdk.variant.variantcontext.VariantContext; + +import java.util.Set; + +public interface VcfRecordFactory { + VcfRecord create(VariantContext variantContext, Set pathogenicClasses); +} diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java similarity index 93% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java index fc816de..572478e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java @@ -1,7 +1,8 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf; import htsjdk.variant.variantcontext.Allele; import htsjdk.variant.variantcontext.VariantContext; +import org.molgenis.vcf.inheritance.matcher.vcf.meta.VepMetadata; import org.molgenis.vcf.inheritance.matcher.model.InheritanceMode; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; @@ -18,11 +19,11 @@ public VcfRecordFactoryImpl(VepMetadata vepMetadata) { } @Override - public VariantRecord create(VariantContext variantContext, Set pathogenicClasses) { + public VcfRecord create(VariantContext variantContext, Set pathogenicClasses) { Set geneInfos = getVcfGeneInfos(variantContext); Set pathogenicAlleles = getPathogenicAlleles(variantContext, vepMetadata, pathogenicClasses); - return new VariantRecord(variantContext, pathogenicAlleles, geneInfos); + return new VcfRecord(variantContext, pathogenicAlleles, geneInfos); } private Set getVcfGeneInfos(VariantContext variantContext) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/MissingInfoException.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/MissingInfoException.java similarity index 84% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/MissingInfoException.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/MissingInfoException.java index 26e3469..2b451fc 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/MissingInfoException.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/MissingInfoException.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf.meta; import java.io.Serial; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationException.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/MissingVepAnnotationException.java similarity index 85% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationException.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/MissingVepAnnotationException.java index 6de9873..ce01a13 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationException.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/MissingVepAnnotationException.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf.meta; import java.io.Serial; diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/VepMetadata.java similarity index 97% rename from src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java rename to src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/VepMetadata.java index e6e4d27..d8dedaf 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/VepMetadata.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/meta/VepMetadata.java @@ -1,4 +1,4 @@ -package org.molgenis.vcf.inheritance.matcher; +package org.molgenis.vcf.inheritance.matcher.vcf.meta; import htsjdk.variant.vcf.VCFHeader; import htsjdk.variant.vcf.VCFInfoHeaderLine; diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingInfoExceptionTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingInfoExceptionTest.java index 24b98c9..af8531e 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingInfoExceptionTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingInfoExceptionTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import org.molgenis.vcf.inheritance.matcher.vcf.meta.MissingInfoException; class MissingInfoExceptionTest { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationExceptionTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationExceptionTest.java index 914b6a9..d3144ea 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationExceptionTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/MissingVepAnnotationExceptionTest.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; +import org.molgenis.vcf.inheritance.matcher.vcf.meta.MissingVepAnnotationException; class MissingVepAnnotationExceptionTest { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java index dfe4a16..aac026c 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/PedigreeInheritanceCheckerTest.java @@ -9,6 +9,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.molgenis.vcf.inheritance.matcher.checker.*; import org.molgenis.vcf.inheritance.matcher.model.*; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.utils.sample.model.Pedigree; import java.util.Set; @@ -46,70 +47,70 @@ void setUp() { @Test void testAdPotential() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(adChecker.check(variantRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.AD); + when(adChecker.check(vcfRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.AD); assertEquals(POTENTIAL, actual); } @Test void testAdIpTrue() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(adNonPenetranceChecker.check(variantRecord, family)).thenReturn(TRUE); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.AD_IP); + when(adNonPenetranceChecker.check(vcfRecord, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.AD_IP); assertEquals(TRUE, actual); } @Test void testArPotential() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(arChecker.check(variantRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.AR); + when(arChecker.check(vcfRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.AR); assertEquals(POTENTIAL, actual); } @Test void testXldFalse() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(xldChecker.check(variantRecord, family)).thenReturn(FALSE); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.XLD); + when(xldChecker.check(vcfRecord, family)).thenReturn(FALSE); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.XLD); assertEquals(FALSE, actual); } @Test void testXlrPotential() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(xlrChecker.check(variantRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.XLR); + when(xlrChecker.check(vcfRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.XLR); assertEquals(POTENTIAL, actual); } @Test void testYlTrue() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(ylChecker.check(variantRecord, family)).thenReturn(TRUE); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.YL); + when(ylChecker.check(vcfRecord, family)).thenReturn(TRUE); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.YL); assertEquals(TRUE, actual); } @Test void testMtPotential() { VariantContext vc = mock(VariantContext.class); - VariantRecord variantRecord = new VariantRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); + VcfRecord vcfRecord = new VcfRecord(vc, Set.of(Allele.ALT_A, Allele.ALT_G), Set.of(new GeneInfo("","",Set.of(InheritanceMode.AD_IP)))); Pedigree family = mock(Pedigree.class); - when(mtChecker.check(variantRecord, family)).thenReturn(POTENTIAL); - MatchEnum actual = pedigreeInheritanceChecker.check(variantRecord, family, InheritanceMode.MT); + when(mtChecker.check(vcfRecord, family)).thenReturn(POTENTIAL); + MatchEnum actual = pedigreeInheritanceChecker.check(vcfRecord, family, InheritanceMode.MT); assertEquals(POTENTIAL, actual); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java index e28c86a..f875f0b 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/VariantContextUtilsTest.java @@ -8,12 +8,14 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.molgenis.vcf.inheritance.matcher.vcf.VariantContextUtils; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; @ExtendWith(MockitoExtension.class) class VariantContextUtilsTest { @Mock - private VariantRecord variantContext; + private VcfRecord variantContext; @Test void onAutosomeTrue() { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java index 6aa2e0c..a059043 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdCheckerTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,10 +31,10 @@ class AdCheckerTest { final AdChecker adChecker = new AdChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adChecker.check(variantRecord, family)); + assertEquals(expected, adChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java index 23020a2..5691ede 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/AdNonPenCheckerTest.java @@ -24,7 +24,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; @@ -39,10 +39,10 @@ class AdNonPenCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, adNonPenetranceChecker.check(variantRecord, family)); + assertEquals(expected, adNonPenetranceChecker.check(vcfRecord, family)); } @Test @@ -50,7 +50,7 @@ void testCheckAd() { VariantContext variantContext = mock(VariantContext.class); Pedigree family = mock(Pedigree.class); - assertEquals(FALSE, adNonPenetranceChecker.check(new VariantRecord(variantContext, Set.of(ALT_A,ALT_G,ALT_N), Set.of(new GeneInfo("GENE1", "SOURCE", emptySet()))), family)); + assertEquals(FALSE, adNonPenetranceChecker.check(new VcfRecord(variantContext, Set.of(ALT_A,ALT_G,ALT_N), Set.of(new GeneInfo("GENE1", "SOURCE", emptySet()))), family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java index 7332199..defce5e 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCheckerTest.java @@ -17,7 +17,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -31,10 +31,10 @@ class ArCheckerTest { final ArChecker arChecker = new ArChecker(); @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, arChecker.check(variantRecord, family)); + assertEquals(expected, arChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java index f84180d..69fa6eb 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/ArCompoundCheckerTest.java @@ -23,7 +23,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.*; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -36,12 +36,12 @@ class ArCompoundCheckerTest { @ParameterizedTest(name = "{index} {4}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Map> geneVariantMap, + void check(VcfRecord vcfRecord, Map> geneVariantMap, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); ArCompoundChecker arCompoundChecker = new ArCompoundChecker(); - Map> compounds = arCompoundChecker.check(geneVariantMap, variantRecord, family); + Map> compounds = arCompoundChecker.check(geneVariantMap, vcfRecord, family); if (expected == FALSE) { assertTrue(isEmpty(compounds)); } else if (expected == TRUE) { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java index 83c0b1b..4006ee1 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/DeNovoCheckerTest.java @@ -14,7 +14,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -28,11 +28,11 @@ class DeNovoCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); Sample individual = family.getMembers().get("Patient"); - assertEquals(expected, deNovoChecker.checkDeNovo(variantRecord, individual)); + assertEquals(expected, deNovoChecker.checkDeNovo(vcfRecord, individual)); } private static Stream provideTestCases() throws IOException { @@ -52,12 +52,12 @@ private static Stream provideTestCases() throws IOException { Pedigree family = PedigreeTestUtil .createFamily(probandSex, AffectedStatus.MISSING, AffectedStatus.MISSING, AffectedStatus.MISSING, "FAM001"); - VariantRecord variantRecord = VariantContextTestUtil + VcfRecord vcfRecord = VariantContextTestUtil .createVariantContext(Arrays.asList(createGenotype("Patient", probandGt), createGenotype("Father", fatherGt), createGenotype("Mother", motherGt)), "", chrom); - return Arguments.of(variantRecord, family, expected, testName); + return Arguments.of(vcfRecord, family, expected, testName); }); } } \ No newline at end of file diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java index 530f80f..4c8f202 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/MtCheckerTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -32,10 +32,10 @@ class MtCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, mtChecker.check(variantRecord, family)); + assertEquals(expected, mtChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java index 907e4f3..7479dde 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XldCheckerTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -29,10 +29,10 @@ class XldCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xldChecker.check(variantRecord, family)); + assertEquals(expected, xldChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java index 9b9e3cd..56cdfe3 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/XlrCheckerTest.java @@ -15,7 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -29,10 +29,10 @@ class XlrCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, xlrChecker.check(variantRecord, family)); + assertEquals(expected, xlrChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java index f6bd757..d2851a1 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/checker/YlCheckerTest.java @@ -6,7 +6,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.junit.jupiter.MockitoExtension; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; import org.molgenis.vcf.inheritance.matcher.util.VariantContextTestUtil; import org.molgenis.vcf.utils.sample.model.AffectedStatus; @@ -32,10 +32,10 @@ class YlCheckerTest { @ParameterizedTest(name = "{index} {3}") @MethodSource("provideTestCases") - void check(VariantRecord variantRecord, Pedigree family, String expectedString, + void check(VcfRecord vcfRecord, Pedigree family, String expectedString, String displayName) { MatchEnum expected = mapExpectedString(expectedString); - assertEquals(expected, ylChecker.check(variantRecord, family)); + assertEquals(expected, ylChecker.check(vcfRecord, family)); } private static Stream provideTestCases() throws IOException { diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java index 4edd6a8..447c57d 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/util/VariantContextTestUtil.java @@ -4,7 +4,7 @@ import htsjdk.variant.variantcontext.Genotype; import htsjdk.variant.variantcontext.GenotypeBuilder; import htsjdk.variant.variantcontext.VariantContextBuilder; -import org.molgenis.vcf.inheritance.matcher.VariantRecord; +import org.molgenis.vcf.inheritance.matcher.vcf.VcfRecord; import org.molgenis.vcf.inheritance.matcher.model.GeneInfo; import org.molgenis.vcf.inheritance.matcher.model.MatchEnum; @@ -18,11 +18,11 @@ public class VariantContextTestUtil { public static final Allele REF = Allele.REF_T; - public static VariantRecord createVariantContext(List genotypes, String vepData) { + public static VcfRecord createVariantContext(List genotypes, String vepData) { return createVariantContext(genotypes, vepData, "1"); } - public static VariantRecord createVariantContext(List genotypes, String vepData, String contig) { + public static VcfRecord createVariantContext(List genotypes, String vepData, String contig) { VariantContextBuilder builder = new VariantContextBuilder(); builder.chr(contig); builder.start(12345); @@ -31,7 +31,7 @@ public static VariantRecord createVariantContext(List genotypes, Strin builder.genotypes(genotypes); builder.attribute("CSQ", vepData); - return new VariantRecord(builder.make(), Set.of(ALT_A,ALT_G,ALT_N), Set.of(new GeneInfo("GENE1", "SOURCE", emptySet()))); + return new VcfRecord(builder.make(), Set.of(ALT_A,ALT_G,ALT_N), Set.of(new GeneInfo("GENE1", "SOURCE", emptySet()))); } public static Genotype createGenotype(String sample, String gt) { From ad9f48888830e3733cebb8025d19b42cd605069a Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 26 Sep 2024 15:30:57 +0200 Subject: [PATCH 16/28] Fix refactor artifact --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7bc438e..5fe2080 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ hs_err_pid* /.idea/ /target/ -/vip-inheritanceResult-matcher.iml +/vip-inheritance-matcher.iml From d302096c4d21435e6bdb346722f0128f4f6e9d6e Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 26 Sep 2024 15:33:45 +0200 Subject: [PATCH 17/28] Rename classes param --- .../vcf/inheritance/matcher/AppCommandLineOptions.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java index a460fb0..421f29b 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java @@ -24,8 +24,8 @@ class AppCommandLineOptions { static final String OPT_DEBUG_LONG = "debug"; static final String OPT_VERSION = "v"; static final String OPT_VERSION_LONG = "version"; - static final String OPT_CLASSES = "pc"; - static final String OPT_CLASSES_LONG = "pathogenicClasses"; + static final String OPT_CLASSES = "c"; + static final String OPT_CLASSES_LONG = "classes"; private static final Options APP_OPTIONS; private static final Options APP_VERSION_OPTIONS; From 1be5ee0a8cb7b163eba2c478ebe4bf2c25b74f3e Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 26 Sep 2024 15:35:31 +0200 Subject: [PATCH 18/28] Update docs --- README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 96d2b67..d9780ab 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ usage: java -jar vcf-inheritance-matcher.jar -i [-o ] [-pd (.ped). -pb,--probands Comma-separated list of proband individual identifiers. + -c,--classes Values in the VIPC subfield of VEP for which + inheritance should be calculated. -f,--force Override the output file if it already exists. -d,--debug Enable debug mode (additional logging). @@ -80,32 +82,31 @@ usage: java -jar vcf-inheritance-matcher.jar -i [-o ] [-pd - XLR: X-linked recessive - XLD: X-linked dominant - AR_C: Autosomal recessive compound hetrozygote -- AD_IP: Autosomal dominant incomplete penetrance. +- AD_IP: Autosomal dominant incomplete penetrance ### Inheritance mode rules Possible inheritance modes are calculated on the following rules: #### AR: -- Affected samples have to be homozygote ALT. -- Unaffected samples cannot be homozygous ALT. +- Affected individuals cannot have the REF allele. +- Unaffected individuals cannot have 2 alleles that were seen in affected individuals. #### AR compound hetrozygote: ##### For unphased data: -- Affected samples need to have both variants. -- Unaffected samples cannot have both variants. +- Affected individuals need to have both variants. +- Unaffected individuals cannot have both variants. ##### For phased data: -- Affected samples need to have both variants on different alleles. -- Unaffected samples cannot have both variants on different alleles, however they can have both variants on the same alleles. +- Affected individuals need to have both variants on different alleles. +- Unaffected individuals cannot have both variants on different alleles, however they can have both variants on the same alleles. #### AD: -- Affected samples have to carry the ALT allele. -Unaffected samples have to be homozygous REF. +- Affected individuals have to carry an ALT allele. +- Unaffected individuals cannot carry the same ALT allele as an unaffected individual. #### AD imcomplete penetrance: -- Affected samples have to carry the ALT allele. -- Unaffected samples have to be homozygous REF, unless the gene on which the variant lies is also on the provided non-penetrance list. +- Affected individuals have to carry an ALT allele. #### XLD: -- Affected samples have to have at least one ALT allele. -- Male unaffected patients cannot have the ALT allele, female unaffected samples can have a single ALT allele due to X inactivation. +- Affected individuals have to have at least one ALT allele. +- Male unaffected individuals cannot have the same ALT allele as seen in affected individuals, female unaffected samples can have a single ALT allele that has also been seen in affected individuals, due to X inactivation. #### XLR: -- Female affected samples have to be homozygous ALT, male affected patients have to be homozygous ALT or have only the ALT allele. -- Female unaffected samples cannot be homozygous ALT, males cannot be homozygous ALT and connot have only the REF allele. +- Female affected individuals have to carry two ALT alleles, male affected individuals have to carry two ALT alleles or have only an ALT allele. +- Female unaffected individuals cannot have 2 alleles that were seen in affected individuals, males cannot have 2 alleles that were seen in affected samples and cannot have only an ALT allele that was seen in affected individuals. #### XL: - If the variant is XLD or XLR it is also considered XL. #### Denovo: From dede5eb2d781a7272c43b4e48b759a2b7378cdfb Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 26 Sep 2024 15:48:49 +0200 Subject: [PATCH 19/28] Fix IT tests --- src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java index 627eff3..71a7c28 100644 --- a/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java +++ b/src/test/java/org/molgenis/vcf/inheritance/matcher/AppIT.java @@ -37,7 +37,7 @@ void testNoPed() throws IOException { String inputFile = ResourceUtils.getFile("classpath:integration.vcf").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pc", "P"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-c", "P"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); @@ -54,7 +54,7 @@ void testProband() throws IOException { String pedigree = ResourceUtils.getFile("classpath:pedigree_complex.ped").toString(); String outputFile = sharedTempDir.resolve("actual.vcf").toString(); - String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-pc","P,B"}; + String[] args = {"-i", inputFile, "-o", outputFile, "-pd", pedigree, "-pb", "Patient,Patient2", "--force" ,"-c","P,B"}; SpringApplication.run(App.class, args); String outputVcf = Files.readString(Path.of(outputFile)); From a6a4a1cfc653f8d51309052a83c353a96be3e79a Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 2 Oct 2024 12:00:12 +0200 Subject: [PATCH 20/28] Update java dependencies and move Travis to GraalVM --- .travis.yml | 4 ++++ install-graal.sh | 17 +++++++++++++++++ pom.xml | 14 +++++++------- 3 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 install-graal.sh diff --git a/.travis.yml b/.travis.yml index 6a491e7..f2bbc6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ jdk: openjdk17 cache: directories: - "$HOME/.m2" + - "$HOME/graalvm" branches: only: - main @@ -15,6 +16,9 @@ addons: token: secure: B8j40t3XBkCA3hruTtZH1AP1H2QhZFYKHrpvwpfo9cYihP4h6ynXeelyEhPbjao4flAnCtiNzUXq7/qAb7di1SPA+607Ip12EGxPwLGosoQlNEHY1js06mpzSqUh80cZDz1SAzJpvkGQjUHPUud2Namx4cQhdng++t5D5SlI7GZbqqC66/34UGI/qIy2CynNA2BFZRZ7u8HuU8wGenAGcXWP4aFZrVPc9Jr0hzSEYQTg5KizWdqiZ5aCEm8Z7ikJtyyTx2ILIJHOk0ybofwpo9X+gz0MxVhTR1F44WM/sducG2dfdFfstneVDP9qWuxdmV7k2d/YjwtLUlPLLmNxXWcsL/8qGP3vo5793o6+MA2yqSfriTm5ahOdgDiewQYZf/MtR6muRVj58WGITCCz4ITJQpg9ouZBgaae6spGC7yQkHfvy3AiVGXzrIJOav7g0e2ZZ0ctYqQHvqosy94JT1pSsTcwyzyAGsWz0CS9fECG4V4RAoWDP3owR5wyHFvbQjZHHRAeVrI4yfw/BGxVDnX+rhEbdRlEbhGTHkmgHuQDf2dGYvPVLEoYT6H73vL2HyAGFhzW0bqY2wNqBwXC9xn4rZ9vvpIS/nqdyBA7ZYNi9oHERf6YkhLfObSiobdtGzgyY+InsMH85DOL9//rWOwOVccruA8GGG2f0wA6YKc= before_install: + - ./install-graal.sh $HOME + - export JAVA_HOME=$HOME/graalvm/graalvm + - export PATH=JAVA_HOME/bin:$PATH - cp travis.settings.xml $HOME/.m2/settings.xml script: - mvn clean install sonar:sonar -Pcoverage -Dsonar.projectKey=molgenis_vip-inheritance-matcher diff --git a/install-graal.sh b/install-graal.sh new file mode 100644 index 0000000..b341c34 --- /dev/null +++ b/install-graal.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +HOME=$1 +if [ -z "$HOME" ]; then + echo "Missing home dir parameter"; + exit 1; +else + if [ ! -d "$HOME/graalvm/graalvm" ]; then + echo "GraalVM is not cached, installing..."; + wget https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz; + mkdir -p $HOME/graalvm; + tar -xzf graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz -C $HOME/graalvm; + mv $HOME/graalvm/graalvm-community-openjdk-21.0.2+13.1 $HOME/graalvm/graalvm + else + echo "Using cached GraalVM"; + fi +fi \ No newline at end of file diff --git a/pom.xml b/pom.xml index ef06194..a8f7b13 100644 --- a/pom.xml +++ b/pom.xml @@ -6,13 +6,13 @@ org.springframework.boot spring-boot-starter-parent - 3.2.2 + 3.3.4 org.molgenis vip-inheritance-matcher - 3.1.1 + 3.2.0 vip-inheritance-matcher Annotates VCF samples with mendelian violation and possible compound flags and @@ -42,12 +42,12 @@ - 17 - 1.6.0 + 21 + 1.9.0 - 0.8.11 - 4.1.0 - 2.0.0 + 0.8.12 + 4.1.1 + 2.0.1 From 49afd6f3b348010acb89d7e166a34c0762304973 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 3 Oct 2024 16:11:37 +0200 Subject: [PATCH 21/28] Fix permissions on install-graal.sh --- install-graal.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 install-graal.sh diff --git a/install-graal.sh b/install-graal.sh old mode 100644 new mode 100755 From 0b05610ee10e0eae237bfc23f243153a4439a4c3 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 10 Oct 2024 08:43:17 +0200 Subject: [PATCH 22/28] Fix vcf metadata --- .../org/molgenis/vcf/inheritance/matcher/Annotator.java | 7 +++---- src/test/resources/expected_noParents.vcf | 6 +++--- src/test/resources/expected_noPed.vcf | 6 +++--- src/test/resources/expected_noVEPinheritance.vcf | 6 +++--- src/test/resources/expected_probands.vcf | 6 +++--- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java index 142e3c4..009fee0 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/Annotator.java @@ -35,11 +35,10 @@ public class Annotator { VCFHeader annotateHeader(VCFHeader vcfHeader) { vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MODES, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "An enumeration of possible inheritance modes based on the pedigree of the sample. Potential values: AD, AD_IP, AR, AR_C, XLR, XLD")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(POSSIBLE_COMPOUND, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Possible Compound hetrozygote variants.")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(DENOVO, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.Integer, "De novo variant.")); - vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MATCH, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.Integer, "Inheritance Match: Genotypes, affected statuses and known gene inheritance patterns match.")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(POSSIBLE_COMPOUND, 1, VCFHeaderLineType.String, "Possible Compound hetrozygote variants.")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(DENOVO, 1, VCFHeaderLineType.Integer, "De novo variant.")); + vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(INHERITANCE_MATCH, 1, VCFHeaderLineType.Integer, "Inheritance Match: Genotypes, affected statuses and known gene inheritance patterns match.")); vcfHeader.addMetaDataLine(new VCFFormatHeaderLine(MATCHING_GENES, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Genes with a (potential) inheritance match.")); - Set headerLines = new LinkedHashSet<>(); //workaround for "Escaped doublequotes in INFO descriptions result in invalid VCF file" // https://github.com/samtools/htsjdk/issues/1661 diff --git a/src/test/resources/expected_noParents.vcf b/src/test/resources/expected_noParents.vcf index a7a9b63..528ddaf 100644 --- a/src/test/resources/expected_noParents.vcf +++ b/src/test/resources/expected_noParents.vcf @@ -3,10 +3,10 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= +##FORMAT= ##INFO= ##INFO= ##INFO= diff --git a/src/test/resources/expected_noPed.vcf b/src/test/resources/expected_noPed.vcf index 46213fc..2b57aba 100644 --- a/src/test/resources/expected_noPed.vcf +++ b/src/test/resources/expected_noPed.vcf @@ -3,10 +3,10 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= +##FORMAT= ##INFO= ##INFO= ##INFO= diff --git a/src/test/resources/expected_noVEPinheritance.vcf b/src/test/resources/expected_noVEPinheritance.vcf index ba73bff..8d1451e 100644 --- a/src/test/resources/expected_noVEPinheritance.vcf +++ b/src/test/resources/expected_noVEPinheritance.vcf @@ -3,10 +3,10 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= +##FORMAT= ##INFO= ##INFO= ##INFO= diff --git a/src/test/resources/expected_probands.vcf b/src/test/resources/expected_probands.vcf index b81c6b7..c00c474 100644 --- a/src/test/resources/expected_probands.vcf +++ b/src/test/resources/expected_probands.vcf @@ -3,10 +3,10 @@ ##FORMAT= ##FORMAT= ##FORMAT= -##FORMAT= -##FORMAT= +##FORMAT= +##FORMAT= ##FORMAT= -##FORMAT= +##FORMAT= ##INFO= ##INFO= ##INFO= From 5f7ae112394a5c1882450adc7c5d36478065a6ff Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Thu, 10 Oct 2024 17:04:30 +0200 Subject: [PATCH 23/28] Fix genes with multiple patters --- .../vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java index 572478e..c8cf469 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java @@ -76,7 +76,7 @@ public List getAttributeAsStringList(VariantContext variantContext, Stri private Set mapGeneInheritance(String inheritanceString) { Set modes = new HashSet<>(); - String[] inheritanceModes = inheritanceString.split(","); + String[] inheritanceModes = inheritanceString.split("&"); for (String mode : inheritanceModes) { switch (mode) { case "AR" -> modes.add(InheritanceMode.AR); From e5c316f8e5b10490c748cf1a4ace266973c06574 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Fri, 11 Oct 2024 10:12:01 +0200 Subject: [PATCH 24/28] Update documentation --- README.md | 148 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index d9780ab..61931b4 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ contain the following: ``` -### Added Sample information +## Added Sample information ``` ##FORMAT= ##FORMAT= @@ -61,7 +61,7 @@ contain the following: ##FORMAT= ``` -### Usage +## Usage ``` usage: java -jar vcf-inheritance-matcher.jar -i [-o ] [-pd ] [-pb ] [-np ] [-c] [-f] [-d] @@ -78,56 +78,120 @@ usage: java -jar vcf-inheritance-matcher.jar -i [-o ] [-pd -d,--debug Enable debug mode (additional logging). ``` -### Subinheritance modes: +## Inheritance patterns +- AR: Autosomal recessive +- AD: Autosomal dominant - XLR: X-linked recessive - XLD: X-linked dominant +- YL: Y-linked +- MT: Mitochondrial - AR_C: Autosomal recessive compound hetrozygote - AD_IP: Autosomal dominant incomplete penetrance -### Inheritance mode rules -Possible inheritance modes are calculated on the following rules: -#### AR: -- Affected individuals cannot have the REF allele. -- Unaffected individuals cannot have 2 alleles that were seen in affected individuals. -#### AR compound hetrozygote: -##### For unphased data: -- Affected individuals need to have both variants. -- Unaffected individuals cannot have both variants. -##### For phased data: -- Affected individuals need to have both variants on different alleles. -- Unaffected individuals cannot have both variants on different alleles, however they can have both variants on the same alleles. -#### AD: -- Affected individuals have to carry an ALT allele. -- Unaffected individuals cannot carry the same ALT allele as an unaffected individual. -#### AD imcomplete penetrance: -- Affected individuals have to carry an ALT allele. -#### XLD: -- Affected individuals have to have at least one ALT allele. -- Male unaffected individuals cannot have the same ALT allele as seen in affected individuals, female unaffected samples can have a single ALT allele that has also been seen in affected individuals, due to X inactivation. -#### XLR: -- Female affected individuals have to carry two ALT alleles, male affected individuals have to carry two ALT alleles or have only an ALT allele. -- Female unaffected individuals cannot have 2 alleles that were seen in affected individuals, males cannot have 2 alleles that were seen in affected samples and cannot have only an ALT allele that was seen in affected individuals. -#### XL: -- If the variant is XLD or XLR it is also considered XL. -#### Denovo: -##### On regular chromosomes: -- Variant are considered denovo if one of the ALT alleles of the proband is not inherited from a parent. -##### On the X chromosome: -- For male probands variants are considered denovo if mother does not have the ALT allele. -- For female probands variants are considered denovo following the same rules as for the other chromosomes. - -### Running without pedigree file +## Inheritance pattern rules +### General rules +For inheritance matching all the members in a family are considered. +This also means that all members in one family are assumed to be blood relatives to the proband(s). +If a pedigree contains one or more members with an unknown affected status, then: +- Inheritance match becomes potential if it would be a match based on members with a known affected status +- The match stays false if it is false based on members with a known affected status + For all patters applies that a homozygote reference call for an affected family member means the pattern does not match. + +#### Autosomal Dominant +1) The variant is not on chromosome X,Y or MT. +2) Affected members need to have at least one alternative allele. +3) Unaffected members cannot have an alternative allele that was also the single alternative allele for any affected member +##### - Missing/partial genotypes: +4) If based on other members the pattern does not match the pattern match will stay false. +5) If based on other members the pattern does match: + - If affected members have one missing allele and one alternative allele, the inheritance match will still be true. + - If affected members have one missing allele and one reference allele, or both alleles are missing values, the inheritance match will be "potential". + - If unaffected members have one missing allele and one alternative allele, the inheritance match will be false if so based on rule 3, and potential if rule 3 would lead to a match. + - If unaffected members have one missing allele and one reference allele, or both alleles are missing values, the inheritance match will be "potential". +#### Autosomal Dominant incomplete penetrance +1) The variant is not on chromosome X,Y or MT. +2) Affected members need to have at least one alternative allele. +3) Unaffected members can have any genotype +##### - Missing/partial genotypes: +4) If based on other members the pattern does not match the pattern match will stay false. +5) If based on other members the pattern does match: + - If affected members have one missing allele and one alternative allele, the inheritance match will still be true. + - If affected members have one missing allele and one reference allele, or both alleles are missing values, the inheritance match will be "potential". +#### Autosomal Recessive +1) The variant is not on chromosome X,Y or MT. +2) Affected members need to have at least two alternative alleles. +3) Unaffected members cannot have a genotype of which both alleles are present in a affected member. +##### - Missing/partial genotypes: +4) If based on other members the pattern does not match the pattern match will stay false. +5) If based on other members the pattern does match: + - If affected members have one missing allele and one alternative allele, or both alleles are missing values, the inheritance match will be potential. + - If affected members have one missing allele and one reference allele, the inheritance match will be false. + - If unaffected members have one missing allele and one alternative allele, or both alleles are missing values, the inheritance match will be potential. + - If unaffected members have one missing allele and one reference allele, the inheritance match will be true. +#### Compound Autosomal Recessive +1) Two variant are present in the same gene for all affected members. +2) Both those variants are not matching the AR inheritance pattern. +3) The variants are not on chromosome X,Y or MT. +4) Affected members need to have at least one alternative allele in for both variants. +3) Unaffected members cannot have the same alternative alleles as an affected member for both variants, they can have the same alternative allele for one of the variants. +##### - Missing/partial genotypes: +6) If based on other members the pattern does not match the pattern match will stay false. +7) If based on other members the pattern does match: + - If affected members have one missing allele or both alleles missing for one or both of the variants the pattern is a potential match. + - If unaffected members have missing alleles in combination with an alternative allele, that has also been seen as a single alternative allele in genotypes of affected members, for both variants that this pattern does not match. + - Other combinations of genotypes with missing alleles will lead to a "potential" match. +#### X-linked Dominant +1) The variant is on chromosome X. +2) Affected members need to have at least one alternative allele. +3) Unaffected members can only have an alternative allele that was also the single alternative allele for any affected member if the genotype is diploid (female), this is possible due to x inactivation. +##### - Missing/partial genotypes: +4) If based on other members the pattern does not match the pattern match will stay false. +5) If based on other members the pattern does match: + - If affected members have one missing allele and one alternative allele, the pattern match will still be true. + - If affected members have one missing allele and one reference allele, or the genotype (either haploid or diploid) is missing, the inheritance match will be "potential". + - If unaffected members have one missing allele or the genotype (either haploid or diploid) is missing, the inheritance match will be "potential". +#### X-linked Recessive +1) The variant is on chromosome X. +2) Affected members cannot have a reference allele. +3) Unaffected members cannot have a genotype of which all alleles are present in a affected member. +##### - Missing/partial genotypes: +4) If based on other members the pattern does not match the pattern match will stay false. +5) If based on other members the pattern does match: + - If affected members have one missing allele and one alternative allele, or the entire genotype is missing, the inheritance match will be potential. + - If affected members have one missing allele and one reference allele, the pattern match will be false. + - If unaffected members have one missing allele and one alternative allele, or the genotype (either haploid or diploid) is missing, the inheritance match will be potential. + - If unaffected members have one missing allele and one reference allele, the pattern match will be true. +#### Y-linked +1) The variant is on chromosome Y. +2) Only genotypes of male family members are taken into account. +3) Affected members need to have an alternative allele. +4) Unaffected members cannot have an alternative allele that was also the alternative allele for any affected member. +##### - Missing/partial genotypes: +5) If based on other members the pattern does not match the result will stay false. +6) If based on other members the pattern does match: + - If any members have a missing genotype the pattern match will be 'potential'. +#### Mitochondrial +1) The variant is on chromosome Y. +2) Affected members need to have an alternative allele. +3) Unaffected members cannot have an alternative allele that was also the alternative allele for any affected member. +##### - Missing/partial genotypes: +4) If based on other members the pattern does not match the result will stay false. +5) If based on other members the pattern does match: + - If any members have a missing genotype the pattern match will be 'potential'. + + +## Running without pedigree file If the tool runs without a ped file, all probands are assumed to be affected. For variants on the X chromosome deploid genotypes are assumed to be female, single alleles are assumed to be male. -### Running without VEP inheritance mode annotations +## Running without VEP inheritance mode annotations If the VEP inheritance mode annotation is missing the tool still calculates all possible inheritance modes. However, the actual matching on genes will obviously never yield a result. -### Compatible Inheritance modes +## Compatible Inheritance modes The VIP inheritance plugin adds a whole range of inheritance modes, however for matching purposes we can only use a subset: AD,AR,XL,XLD,XLR. -#### Supported +### Supported | OMIM Inheritance* | Annotation | |---------------------|------------| | X-LINKED DOMINANT | XD | @@ -135,19 +199,19 @@ The VIP inheritance plugin adds a whole range of inheritance modes, however for | X-LINKED* | XL | | AUTOSOMAL RECESSIVE | AR | | AUTOSOMAL DOMINANT | AD | +| Y-LINKED | YL | +| MITOCHONDRIAL | MT | *: Please note that XL is matched by both XD and XR. -#### Unsupported +### Unsupported | OMIM Inheritance* | Annotation | |---------------------------------|------------| -| Y-LINKED | YL | | PSEUDOAUTOSOMAL RECESSIVE | PR | | PSEUDOAUTOSOMAL DOMINANT | PD | | ISOLATED CASES | IC | | DIGENIC | DG | | DIGENIC RECESSIVE | DGR | | DIGENIC DOMINANT | DGD | -| MITOCHONDRIAL | MT | | MULTIFACTORIAL | MF | | SOMATIC MUTATION | SM | | SOMATIC MOSAICISM | SMM | From 748257bd198c8ba650a22373e8d024e2a97ea5fa Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 15 Oct 2024 12:18:18 +0200 Subject: [PATCH 25/28] Process review comments --- README.md | 8 +++++--- .../vcf/inheritance/matcher/AppCommandLineOptions.java | 2 +- .../vcf/inheritance/matcher/AppCommandLineRunner.java | 2 +- .../vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 61931b4..0a6bc44 100644 --- a/README.md +++ b/README.md @@ -71,8 +71,9 @@ usage: java -jar vcf-inheritance-matcher.jar -i [-o ] [-pd (.ped). -pb,--probands Comma-separated list of proband individual identifiers. - -c,--classes Values in the VIPC subfield of VEP for which - inheritance should be calculated. + -c,--classes Comma-separated list of values in the INFO/CSQ VIPC subfield + to be used in inheritance calculation. + By default inheritance is calculated for all records. -f,--force Override the output file if it already exists. -d,--debug Enable debug mode (additional logging). @@ -95,7 +96,8 @@ This also means that all members in one family are assumed to be blood relatives If a pedigree contains one or more members with an unknown affected status, then: - Inheritance match becomes potential if it would be a match based on members with a known affected status - The match stays false if it is false based on members with a known affected status - For all patters applies that a homozygote reference call for an affected family member means the pattern does not match. + For all patterns applies that a homozygote reference call for an affected family member means the pattern does not match. +The list of supported contigs to determine if a variant is on X,Y,MT or an autosome can be found [here](https://github.com/molgenis/vip-inheritance-matcher/blob/main/src/main/java/org/molgenis/vcf/inheritance/matcher/ContigUtils.java) #### Autosomal Dominant 1) The variant is not on chromosome X,Y or MT. diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java index 421f29b..3bc26ee 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineOptions.java @@ -60,7 +60,7 @@ class AppCommandLineOptions { Option.builder(OPT_CLASSES) .hasArg(true) .longOpt(OPT_CLASSES_LONG) - .desc("Mapping of VIP class to pathogenicity, format: P:LP,P;V:VUS;B:LB,b") + .desc("Comma-separated list of values in the INFO/CSQ VIPC subfield to be used in inheritance calculation.") .build()); appOptions.addOption( Option.builder(OPT_FORCE) diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java index 58faa50..63857a5 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/AppCommandLineRunner.java @@ -116,7 +116,7 @@ private Settings mapSettings(CommandLine commandLine) { } private Set mapPathogenicityClasses(String optionValue) { - return Set.of(optionValue.split(",")); + return Set.of(optionValue.split(",", -1)); } private CommandLine getCommandLine(String[] args) { diff --git a/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java index c8cf469..035c12e 100644 --- a/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java +++ b/src/main/java/org/molgenis/vcf/inheritance/matcher/vcf/VcfRecordFactoryImpl.java @@ -28,7 +28,7 @@ public VcfRecord create(VariantContext variantContext, Set pathogenicCla private Set getVcfGeneInfos(VariantContext variantContext) { List vepValues = getAttributeAsStringList(variantContext, vepMetadata.getVepFieldId()); - Set result = new HashSet<>(); + Set result = new LinkedHashSet<>(); for (String vepValue : vepValues) { String[] vepSplit = vepValue.split("\\|", -1); String geneId = vepSplit[vepMetadata.getGeneIndex()]; From 90346299e291c431134a6a2b201f6f4e427600c1 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 15 Oct 2024 16:21:42 +0200 Subject: [PATCH 26/28] Revert move to GraalVM --- .travis.yml | 6 +----- install-graal.sh | 17 ----------------- 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100755 install-graal.sh diff --git a/.travis.yml b/.travis.yml index f2bbc6f..3336786 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,10 @@ os: linux dist: jammy language: java -jdk: openjdk17 +jdk: openjdk21 cache: directories: - "$HOME/.m2" - - "$HOME/graalvm" branches: only: - main @@ -16,9 +15,6 @@ addons: token: secure: B8j40t3XBkCA3hruTtZH1AP1H2QhZFYKHrpvwpfo9cYihP4h6ynXeelyEhPbjao4flAnCtiNzUXq7/qAb7di1SPA+607Ip12EGxPwLGosoQlNEHY1js06mpzSqUh80cZDz1SAzJpvkGQjUHPUud2Namx4cQhdng++t5D5SlI7GZbqqC66/34UGI/qIy2CynNA2BFZRZ7u8HuU8wGenAGcXWP4aFZrVPc9Jr0hzSEYQTg5KizWdqiZ5aCEm8Z7ikJtyyTx2ILIJHOk0ybofwpo9X+gz0MxVhTR1F44WM/sducG2dfdFfstneVDP9qWuxdmV7k2d/YjwtLUlPLLmNxXWcsL/8qGP3vo5793o6+MA2yqSfriTm5ahOdgDiewQYZf/MtR6muRVj58WGITCCz4ITJQpg9ouZBgaae6spGC7yQkHfvy3AiVGXzrIJOav7g0e2ZZ0ctYqQHvqosy94JT1pSsTcwyzyAGsWz0CS9fECG4V4RAoWDP3owR5wyHFvbQjZHHRAeVrI4yfw/BGxVDnX+rhEbdRlEbhGTHkmgHuQDf2dGYvPVLEoYT6H73vL2HyAGFhzW0bqY2wNqBwXC9xn4rZ9vvpIS/nqdyBA7ZYNi9oHERf6YkhLfObSiobdtGzgyY+InsMH85DOL9//rWOwOVccruA8GGG2f0wA6YKc= before_install: - - ./install-graal.sh $HOME - - export JAVA_HOME=$HOME/graalvm/graalvm - - export PATH=JAVA_HOME/bin:$PATH - cp travis.settings.xml $HOME/.m2/settings.xml script: - mvn clean install sonar:sonar -Pcoverage -Dsonar.projectKey=molgenis_vip-inheritance-matcher diff --git a/install-graal.sh b/install-graal.sh deleted file mode 100755 index b341c34..0000000 --- a/install-graal.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -HOME=$1 -if [ -z "$HOME" ]; then - echo "Missing home dir parameter"; - exit 1; -else - if [ ! -d "$HOME/graalvm/graalvm" ]; then - echo "GraalVM is not cached, installing..."; - wget https://github.com/graalvm/graalvm-ce-builds/releases/download/jdk-21.0.2/graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz; - mkdir -p $HOME/graalvm; - tar -xzf graalvm-community-jdk-21.0.2_linux-x64_bin.tar.gz -C $HOME/graalvm; - mv $HOME/graalvm/graalvm-community-openjdk-21.0.2+13.1 $HOME/graalvm/graalvm - else - echo "Using cached GraalVM"; - fi -fi \ No newline at end of file From dde739bb598ba1cb1a12d38de363e8a5d1078cd5 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Tue, 15 Oct 2024 18:40:00 +0200 Subject: [PATCH 27/28] Update vip-utils --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a8f7b13..e3a38ee 100644 --- a/pom.xml +++ b/pom.xml @@ -47,7 +47,7 @@ 0.8.12 4.1.1 - 2.0.1 + 2.0.2 From be08e462f5764367c6a880452187a406d146f2d9 Mon Sep 17 00:00:00 2001 From: "bart.charbon" Date: Wed, 16 Oct 2024 07:07:26 +0200 Subject: [PATCH 28/28] update java requirement --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a6bc44..20aca18 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ annotates VCF samples with denovo and possible compound flags and matching inheritance modes and genes. ## Requirements -- Java 17 +- Java 21 Input VCF file should contain single ALT alleles per line and be annotated VEP. Input should be annotated with [VIP inheritance VEP plugin](https://github.com/molgenis/vip/blob/master/resources/vep/plugins/Inheritance.pm) For full functionality.