diff --git a/src/main/java/org/pharmgkb/pharmcat/BaseConfig.java b/src/main/java/org/pharmgkb/pharmcat/BaseConfig.java index c641c627..522cfb77 100644 --- a/src/main/java/org/pharmgkb/pharmcat/BaseConfig.java +++ b/src/main/java/org/pharmgkb/pharmcat/BaseConfig.java @@ -9,6 +9,8 @@ import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import com.google.common.base.Splitter; import org.apache.commons.io.FilenameUtils; @@ -28,7 +30,8 @@ public class BaseConfig { public static final String MATCHER_SUFFIX = ".match"; public static final String PHENOTYPER_SUFFIX = ".phenotype"; public static final String REPORTER_SUFFIX = ".report"; - public static final String OUTSIDE_SUFFIX = ".outside"; + public static final Pattern OUTSIDE_SUFFIX_PATTERN = Pattern.compile("^(.+)\\.outside\\d*$"); + public static final Pattern OUTSIDE_FILENAME_PATTERN = Pattern.compile("^(.+)\\.outside\\d*\\.tsv$"); private static final Splitter sf_commaSplitter = Splitter.on(",").trimResults().omitEmptyStrings(); boolean runMatcher = true; Path definitionDir; @@ -170,8 +173,9 @@ public static String getBaseFilename(Path inputFile) { if (filename.endsWith(MATCHER_SUFFIX)) { filename = filename.substring(0, filename.length() - MATCHER_SUFFIX.length()); } - if (filename.endsWith(OUTSIDE_SUFFIX)) { - filename = filename.substring(0, filename.length() - OUTSIDE_SUFFIX.length()); + Matcher m = BaseConfig.OUTSIDE_SUFFIX_PATTERN.matcher(filename); + if (m.matches()) { + filename = m.group(1); } if (filename.endsWith(PHENOTYPER_SUFFIX)) { filename = filename.substring(0, filename.length() - PHENOTYPER_SUFFIX.length()); diff --git a/src/main/java/org/pharmgkb/pharmcat/BatchPharmCAT.java b/src/main/java/org/pharmgkb/pharmcat/BatchPharmCAT.java index 7717bf74..d5deb815 100644 --- a/src/main/java/org/pharmgkb/pharmcat/BatchPharmCAT.java +++ b/src/main/java/org/pharmgkb/pharmcat/BatchPharmCAT.java @@ -6,15 +6,16 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.stream.Collectors; import com.google.common.base.Preconditions; import com.google.common.base.Stopwatch; import org.apache.commons.io.FileUtils; @@ -36,7 +37,7 @@ public class BatchPharmCAT { private final boolean m_verbose; private final Map m_vcfFilesToProcess = new TreeMap<>(); private final Map m_matchFilesToProcess = new TreeMap<>(); - private final Map m_outsideCallFilesToProcess = new TreeMap<>(); + private final Map> m_outsideCallFilesToProcess = new TreeMap<>(); private final Map m_phenotypeFilesToProcess = new TreeMap<>(); @@ -158,9 +159,9 @@ private BatchPharmCAT(BaseConfig config, Path inputDir, @Nullable Path vcfFile, if (config.runPhenotyper) { m_matchFilesToProcess.put(basename, file); } - } else if (name.endsWith(BaseConfig.OUTSIDE_SUFFIX + ".tsv")) { + } else if (BaseConfig.OUTSIDE_FILENAME_PATTERN.matcher(name).matches()) { if (config.runPhenotyper) { - m_outsideCallFilesToProcess.put(basename, file); + m_outsideCallFilesToProcess.computeIfAbsent(basename, k -> new ArrayList<>()).add(file); } } else if (name.endsWith(BaseConfig.PHENOTYPER_SUFFIX + ".json")) { if (config.runReporter) { @@ -175,12 +176,11 @@ private BatchPharmCAT(BaseConfig config, Path inputDir, @Nullable Path vcfFile, return; } // input VCF file trumps other VCF files in inputDir - Set vcfBasenames = m_vcfFilesToProcess.keySet(); String vcfBasename = BaseConfig.getBaseFilename(vcfFile); m_vcfFilesToProcess.clear(); m_vcfFilesToProcess.put(vcfBasename, new VcfFile(vcfFile)); if (config.runPhenotyper) { - Path f = m_outsideCallFilesToProcess.get(vcfBasename); + List f = m_outsideCallFilesToProcess.get(vcfBasename); m_outsideCallFilesToProcess.clear(); if (f != null) { m_outsideCallFilesToProcess.put(vcfBasename, f); @@ -198,7 +198,7 @@ private BatchPharmCAT(BaseConfig config, Path inputDir, @Nullable Path vcfFile, } if (config.runPhenotyper) { types.add("*" + BaseConfig.MATCHER_SUFFIX + ".json"); - types.add("*" + BaseConfig.OUTSIDE_SUFFIX + ".tsv"); + types.add(BaseConfig.OUTSIDE_FILENAME_PATTERN.pattern()); } if (config.runReporter) { types.add("*" + BaseConfig.PHENOTYPER_SUFFIX + ".json"); @@ -335,7 +335,7 @@ public class Builder { private String m_sampleId; private boolean m_runPhenotyper; private Path m_piFile; - private Path m_poFile; + private List m_poFile = null; private boolean m_runReporter; private Path m_riFile; private boolean m_singleSample; @@ -418,12 +418,12 @@ private void findPhenotyperFiles(String basename) { } // po file if (m_outsideCallFilesToProcess.containsKey(basename)) { - Path file = m_outsideCallFilesToProcess.get(basename); - m_poFile = pickFirstFile(m_poFile, file); + List files = m_outsideCallFilesToProcess.get(basename); + m_poFile = pickFirst(m_poFile, files); m_outsideCallFilesToProcess.remove(basename); if ((m_piFile == null && !m_config.runMatcher) || (m_piFile == null && m_vcfFile == null)) { - System.out.println("* Warning: lone outside call file (" + m_poFile.getFileName() + + System.out.println("* Warning: lone outside call file (" + printFileNames(m_poFile) + ") with no matching .vcf or " + BaseConfig.MATCHER_SUFFIX + ".json"); } } @@ -457,4 +457,20 @@ private Path pickFirstFile(Path origFile, Path newFile) { } } } + + private List pickFirst(List origList, List newList) { + if (origList == null) { + return newList; + } else { + System.out.println("* Ignoring " + printFileNames(newList) + " - using " + printFileNames(origList) + " instead"); + return origList; + } + } + + private String printFileNames(Collection paths) { + if (paths == null || paths.isEmpty()) { + return ""; + } + return paths.stream().map(p -> p.getFileName().toString()).collect(Collectors.joining(", ")); + } } diff --git a/src/main/java/org/pharmgkb/pharmcat/PharmCAT.java b/src/main/java/org/pharmgkb/pharmcat/PharmCAT.java index 0ee6a26a..12c2140b 100644 --- a/src/main/java/org/pharmgkb/pharmcat/PharmCAT.java +++ b/src/main/java/org/pharmgkb/pharmcat/PharmCAT.java @@ -2,6 +2,7 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -85,16 +86,23 @@ Please specify a VCF file (-vcf)""" } Path phenotyperInputFile = null; - Path phenotyperOutsideCallsFile = null; + List phenotyperOutsideCallsFiles = new ArrayList<>(); if (config.runPhenotyper) { if (cliHelper.hasOption("pi")) { phenotyperInputFile = cliHelper.getValidFile("pi", true); } if (cliHelper.hasOption("po")) { - phenotyperOutsideCallsFile = cliHelper.getValidFile("po", true); + for (String outsidePathString : cliHelper.getValues("po")) { + Path outsidePath = Paths.get(outsidePathString); + if (outsidePath.toFile().exists() && outsidePath.toFile().isFile()) { + phenotyperOutsideCallsFiles.add(outsidePath); + } else { + throw new ReportableException("Not a valid file: '" + outsidePathString); + } + } } - if (vcfFile == null && phenotyperInputFile == null && phenotyperOutsideCallsFile == null) { + if (vcfFile == null && phenotyperInputFile == null && phenotyperOutsideCallsFiles.isEmpty()) { System.out.println(""" No input for Phenotyper! @@ -113,7 +121,7 @@ Please specify a VCF file (-vcf)""" reporterInputFile = cliHelper.getValidFile("ri", true); } - if (vcfFile == null && phenotyperInputFile == null && phenotyperOutsideCallsFile == null && + if (vcfFile == null && phenotyperInputFile == null && phenotyperOutsideCallsFiles.isEmpty() && reporterInputFile == null) { System.out.println( """ @@ -158,7 +166,7 @@ Please specify a VCF file (-vcf)""" Pipeline pipeline = new Pipeline(env, config.runMatcher, vcfFile, sampleId, singleSample, config.topCandidateOnly, config.callCyp2d6, config.findCombinations, config.matcherHtml, - config.runPhenotyper, phenotyperInputFile, phenotyperOutsideCallsFile, + config.runPhenotyper, phenotyperInputFile, phenotyperOutsideCallsFiles, config.runReporter, reporterInputFile, config.reporterTitle, config.reporterSources, config.reporterCompact, config.reporterJson, config.reporterHtml, config.outputDir, config.baseFilename, config.deleteIntermediateFiles, @@ -182,7 +190,7 @@ Please specify a VCF file (-vcf)""" Pipeline pipeline = new Pipeline(env, false, null, null, true, config.topCandidateOnly, config.callCyp2d6, config.findCombinations, config.matcherHtml, - config.runPhenotyper, phenotyperInputFile, phenotyperOutsideCallsFile, + config.runPhenotyper, phenotyperInputFile, phenotyperOutsideCallsFiles, config.runReporter, reporterInputFile, config.reporterTitle, config.reporterSources, config.reporterCompact, config.reporterJson, config.reporterHtml, config.outputDir, config.baseFilename, config.deleteIntermediateFiles, diff --git a/src/main/java/org/pharmgkb/pharmcat/Pipeline.java b/src/main/java/org/pharmgkb/pharmcat/Pipeline.java index 494e939d..b030caa9 100644 --- a/src/main/java/org/pharmgkb/pharmcat/Pipeline.java +++ b/src/main/java/org/pharmgkb/pharmcat/Pipeline.java @@ -7,10 +7,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.concurrent.Callable; +import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; import org.checkerframework.checker.nullness.qual.Nullable; import org.pharmgkb.common.util.AnsiConsole; @@ -57,7 +62,7 @@ public enum Mode { private final boolean m_runPhenotyper; private Path m_phenotyperInputFile; - private Path m_phenotyperOutsideCallsFile; + private List m_phenotyperOutsideCallsFile; private Path m_phenotyperJsonFile; private final boolean m_runReporter; @@ -81,7 +86,7 @@ public enum Mode { public Pipeline(Env env, boolean runMatcher, @Nullable VcfFile vcfFile, @Nullable String sampleId, boolean singleSample, boolean topCandidateOnly, boolean callCyp2d6, boolean findCombinations, boolean matcherHtml, - boolean runPhenotyper, @Nullable Path phenotyperInputFile, @Nullable Path phenotyperOutsideCallsFile, + boolean runPhenotyper, @Nullable Path phenotyperInputFile, @Nullable List phenotyperOutsideCallsFile, boolean runReporter, @Nullable Path reporterInputFile, @Nullable String reporterTitle, @Nullable List reporterSources, boolean reporterCompact, boolean reporterJson, boolean reporterHtml, @Nullable Path outputDir, @Nullable String baseFilename, boolean deleteIntermediateFiles, @@ -113,8 +118,8 @@ public Pipeline(Env env, Path inputFile = m_matcherJsonFile; if (m_phenotyperInputFile != null) { inputFile = m_phenotyperInputFile; - } else if (m_phenotyperOutsideCallsFile != null) { - inputFile = m_phenotyperOutsideCallsFile; + } else if (m_phenotyperOutsideCallsFile != null && !m_phenotyperOutsideCallsFile.isEmpty()) { + inputFile = m_phenotyperOutsideCallsFile.get(0); } if (inputFile == null) { throw new IllegalStateException("No phenotyper input file"); @@ -277,22 +282,32 @@ public PipelineResult call() throws IOException { calls = new ArrayList<>(); } - List outsideCalls = new ArrayList<>(); - if (m_phenotyperOutsideCallsFile != null) { - for (OutsideCall call : OutsideCallParser.parse(m_phenotyperOutsideCallsFile)) { - if (!m_env.hasGene(call.getGene())) { - String msg = "Discarded outside call for " + call.getGene() + " because it is not supported by PharmCAT."; - output.add(AnsiConsole.styleWarning(msg)); - continue; - } - if (!m_env.isActivityScoreGene(call.getGene())) { - if (call.getDiplotype() == null && call.getPhenotype() == null) { - String msg = call.getGene() + " is not an activity score gene but has outside call with only an " + - "activity score. PharmCAT will not be able to provide any recommendations based on this gene."; + Map> outsideCallMap = new HashMap<>(); + SortedSet outsideCalls = new TreeSet<>(); + if (m_phenotyperOutsideCallsFile != null && !m_phenotyperOutsideCallsFile.isEmpty()) { + for (Path outsideCallPath : m_phenotyperOutsideCallsFile) { + for (OutsideCall call : OutsideCallParser.parse(outsideCallPath)) { + String gene = call.getGene(); + if (!m_env.hasGene(gene)) { + String msg = "Discarded outside call for " + gene + " because it is not supported by PharmCAT."; output.add(AnsiConsole.styleWarning(msg)); + continue; + } + if (!m_env.isActivityScoreGene(gene)) { + if (call.getDiplotype() == null && call.getPhenotype() == null) { + String msg = gene + " is not an activity score gene but has outside call with only an " + + "activity score. PharmCAT will not be able to provide any recommendations based on this gene."; + output.add(AnsiConsole.styleWarning(msg)); + } } + outsideCalls.add(call); + outsideCallMap.computeIfAbsent(gene, g -> new HashSet<>()).add(call); + } + } + for (String gene : outsideCallMap.keySet()) { + if (outsideCallMap.get(gene).size() > 1) { + output.add(AnsiConsole.styleWarning("WARNING: Multiple outside calls for " + gene + ".")); } - outsideCalls.add(call); } } @@ -396,11 +411,11 @@ private String getInputDescription() { } builder.append(m_phenotyperInputFile.getFileName()); } - if (m_phenotyperOutsideCallsFile != null) { + if (m_phenotyperOutsideCallsFile != null && !m_phenotyperOutsideCallsFile.isEmpty()) { if (!builder.isEmpty()) { builder.append(", "); } - builder.append(m_phenotyperOutsideCallsFile.getFileName()); + builder.append(m_phenotyperOutsideCallsFile.stream().map(p -> p.getFileName().toString()).collect(Collectors.joining(", "))); } if (m_reporterInputFile != null) { if (!builder.isEmpty()) { diff --git a/src/main/java/org/pharmgkb/pharmcat/phenotype/OutsideCallParser.java b/src/main/java/org/pharmgkb/pharmcat/phenotype/OutsideCallParser.java index 8634d481..01f1a06f 100644 --- a/src/main/java/org/pharmgkb/pharmcat/phenotype/OutsideCallParser.java +++ b/src/main/java/org/pharmgkb/pharmcat/phenotype/OutsideCallParser.java @@ -5,7 +5,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.function.Predicate; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; @@ -56,8 +58,8 @@ public static List parse(Path filePath) throws IOException { return calls; } - public static List parse(String outsideCallData) { - List calls = new ArrayList<>(); + public static Set parse(String outsideCallData) { + Set calls = new HashSet<>(); String[] lines = StringUtils.stripToEmpty(outsideCallData).split("\n"); for (int x = 0; x < lines.length; x += 1) { String line = lines[x]; diff --git a/src/main/java/org/pharmgkb/pharmcat/phenotype/Phenotyper.java b/src/main/java/org/pharmgkb/pharmcat/phenotype/Phenotyper.java index 76ffa65e..aacac1ae 100644 --- a/src/main/java/org/pharmgkb/pharmcat/phenotype/Phenotyper.java +++ b/src/main/java/org/pharmgkb/pharmcat/phenotype/Phenotyper.java @@ -57,14 +57,14 @@ public class Phenotyper { * @param outsideCalls a List of {@link OutsideCall} objects * @param variantWarnings map of VCF warnings, keyed to chromosomal position */ - public Phenotyper(Env env, List geneCalls, List outsideCalls, + public Phenotyper(Env env, List geneCalls, Set outsideCalls, @Nullable Map> variantWarnings) { initialize(geneCalls, outsideCalls, env, DataSource.CPIC, variantWarnings); initialize(geneCalls, outsideCalls, env, DataSource.DPWG, variantWarnings); } - private void initialize(List geneCalls, List outsideCalls, Env env, DataSource source, + private void initialize(List geneCalls, Set outsideCalls, Env env, DataSource source, @Nullable Map> variantWarnings) { SortedMap reportMap = m_geneReports.computeIfAbsent(source, (s) -> new TreeMap<>()); @@ -97,7 +97,6 @@ private void initialize(List geneCalls, List outsideCalls } else { // add alternate outside call - System.out.println("WARNING: Multiple outside calls for " + outsideCall.getGene()); geneReport.addOutsideCall(outsideCall, env); continue; } diff --git a/src/main/java/org/pharmgkb/pharmcat/phenotype/model/OutsideCall.java b/src/main/java/org/pharmgkb/pharmcat/phenotype/model/OutsideCall.java index 72551a29..67e26b93 100644 --- a/src/main/java/org/pharmgkb/pharmcat/phenotype/model/OutsideCall.java +++ b/src/main/java/org/pharmgkb/pharmcat/phenotype/model/OutsideCall.java @@ -1,13 +1,15 @@ package org.pharmgkb.pharmcat.phenotype.model; -import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.SortedSet; import java.util.TreeSet; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; +import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; +import org.pharmgkb.common.util.ComparisonChain; import org.pharmgkb.pharmcat.phenotype.PhenotypeUtils; import org.pharmgkb.pharmcat.reporter.BadOutsideCallException; import org.pharmgkb.pharmcat.util.HaplotypeNameComparator; @@ -18,7 +20,7 @@ * * @author Ryan Whaley */ -public class OutsideCall { +public class OutsideCall implements Comparable { private static final Splitter sf_lineSplitter = Splitter.on("\t").trimResults(); private static final Splitter sf_diplotypeSplitter = Splitter.on("/").trimResults(); private static final String sf_diplotypeSeparator = "/"; @@ -29,10 +31,10 @@ public class OutsideCall { private static final int IDX_ACTIVITY = 3; private final String m_gene; - private String m_diplotype; + private final @Nullable String m_diplotype; private final List m_diplotypes; - private String m_phenotype = null; - private String m_activityScore = null; + private @Nullable String m_phenotype = null; + private @Nullable String m_activityScore = null; private final SortedSet m_haplotypes = new TreeSet<>(HaplotypeNameComparator.getComparator()); /** @@ -52,8 +54,8 @@ public OutsideCall(String line, int lineNumber) throws RuntimeException { throw new BadOutsideCallException("Line " + lineNumber + ": No gene specified"); } - m_diplotype = StringUtils.stripToNull(fields.get(IDX_DIPS)); - if (fields.size() == 2 && (m_diplotype == null || m_diplotype.equals(sf_diplotypeSeparator))) { + String diplotype = StringUtils.stripToNull(fields.get(IDX_DIPS)); + if (fields.size() == 2 && (diplotype == null || diplotype.equals(sf_diplotypeSeparator))) { if (StringUtils.isBlank(fields.get(IDX_DIPS))) { throw new BadOutsideCallException("Line " + lineNumber + ": No diplotype specified"); } else { @@ -61,13 +63,14 @@ public OutsideCall(String line, int lineNumber) throws RuntimeException { } } - if (m_diplotype != null) { - List alleles = new ArrayList<>(); + if (diplotype == null) { + m_diplotype = null; + m_diplotypes = ImmutableList.of(); + } else { // strip any prefix of the gene symbol - for (String allele : sf_diplotypeSplitter.splitToList(m_diplotype)) { - alleles.add(allele.replaceFirst("^" + m_gene + "\\s*", "")); - } - + List alleles = sf_diplotypeSplitter.splitToList(diplotype).stream() + .map(a -> a.replaceFirst("^" + m_gene + "\\s*", "")) + .toList(); // re-join alleles to eliminate white space when gene symbol is used in diplotype m_diplotype = String.join(sf_diplotypeSeparator, alleles); m_diplotypes = ImmutableList.of(m_diplotype); @@ -78,8 +81,6 @@ public OutsideCall(String line, int lineNumber) throws RuntimeException { if (alleles.size() == 2) { m_haplotypes.add(alleles.get(1)); } - } else { - m_diplotypes = ImmutableList.of(); } if (fields.size() >= 3) { @@ -121,11 +122,47 @@ public SortedSet getHaplotypes() { return m_haplotypes; } - public String getPhenotype() { + public @Nullable String getPhenotype() { return m_phenotype; } - public String getActivityScore() { + public @Nullable String getActivityScore() { return m_activityScore; } + + + @Override + public boolean equals(Object o) { + if (!(o instanceof OutsideCall oc)) { + return false; + } + if (o == this) { + return true; + } + // ignore diplotypes and haplotypes because they are derived props + return Objects.equals(m_gene, oc.getGene()) && + Objects.equals(m_diplotype, oc.getDiplotype()) && + Objects.equals(m_phenotype, oc.getPhenotype()) && + Objects.equals(m_activityScore, oc.getActivityScore()) + ; + } + + @Override + public int hashCode() { + return Objects.hash(m_gene, m_diplotype, m_phenotype, m_activityScore); + } + + @Override + public int compareTo(@NonNull OutsideCall o) { + if (this == o) { + return 0; + } + // ignore diplotypes and haplotypes because they are derived props + return new ComparisonChain() + .compare(m_gene, o.getGene()) + .compare(m_diplotype, o.getDiplotype()) + .compare(m_phenotype, o.getPhenotype()) + .compare(m_activityScore, o.getActivityScore()) + .result(); + } } diff --git a/src/test/java/org/pharmgkb/pharmcat/BatchPharmCATTest.java b/src/test/java/org/pharmgkb/pharmcat/BatchPharmCATTest.java index 5237fb7d..700d9f35 100644 --- a/src/test/java/org/pharmgkb/pharmcat/BatchPharmCATTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/BatchPharmCATTest.java @@ -16,6 +16,8 @@ import org.junit.jupiter.api.TestInfo; import org.pharmgkb.common.util.PathUtils; import org.pharmgkb.pharmcat.haplotype.VcfSampleReader; +import org.pharmgkb.pharmcat.phenotype.Phenotyper; +import org.pharmgkb.pharmcat.reporter.model.DataSource; import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemErr; import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemOut; @@ -124,6 +126,44 @@ void twoSamples(TestInfo testInfo) throws Exception { checkForOutputFiles(tmpDir, vcfFiles); } + @Test + void twoOutsideCallsForOneSample(TestInfo testInfo) throws Exception { + Path[] vcfFiles = new Path[] { + PathUtils.getPathToResource("org/pharmgkb/pharmcat/Sample_1.preprocessed.vcf"), + PathUtils.getPathToResource("org/pharmgkb/pharmcat/Sample_2.preprocessed.vcf"), + }; + + Path tmpDir = TestUtils.getTestOutputDir(testInfo, true); + copyFiles(tmpDir, vcfFiles); + + Path outsideFileS2O1 = tmpDir.resolve("Sample_2.outside1.tsv"); + Files.copy(PathUtils.getPathToResource("org/pharmgkb/pharmcat/PharmCATTest-cyp2d6.tsv"), outsideFileS2O1); + + Path outsideFileS2O2 = tmpDir.resolve("Sample_2.outside2.tsv"); + Files.copy(PathUtils.getPathToResource("org/pharmgkb/pharmcat/PharmCATTest-outsideCallsNoRecs.tsv"), outsideFileS2O2); + + String systemOut = tapSystemOut(() -> BatchPharmCAT.main(new String[] { + "-i", tmpDir.toString(), + })); + System.out.println(systemOut); + assertThat(systemOut, containsString("Found 2 VCF files")); + // this should always come out as 2 samples queued, the two outside call files are attached to one sample + assertThat(systemOut, containsString("Queueing up 2 samples")); + assertThat(systemOut, containsString("Done.")); + assertThat(systemOut, not(containsString("FAIL"))); + checkForOutputFiles(tmpDir, vcfFiles); + + Phenotyper phenotyper = Phenotyper.read(tmpDir.resolve("Sample_2.phenotype.json")); + PharmCATTest.checkOutsideDiplotype(phenotyper.findGeneReport(DataSource.CPIC, "CYP2D6").orElse(null), + "CYP2D6*3", "CYP2D6*4"); + PharmCATTest.checkOutsideDiplotype(phenotyper.findGeneReport(DataSource.CPIC, "CYP4F2").orElse(null), + "*1", "*3"); + PharmCATTest.checkOutsideDiplotype(phenotyper.findGeneReport(DataSource.CPIC, "IFNL3").orElse(null), + "rs12979860 variant (T)", "rs12979860 variant (T)"); + + + } + @Test void sixSamples(TestInfo testInfo) throws Exception { @@ -355,7 +395,7 @@ private void checkForOutputFiles(Path dir, Path... inputFiles) throws IOExceptio checked = true; } if (extension.endsWith(".vcf") || extension.equals(BaseConfig.MATCHER_SUFFIX + ".json") || - extension.equals(BaseConfig.OUTSIDE_SUFFIX + "..tsv")) { + BaseConfig.OUTSIDE_SUFFIX_PATTERN.matcher(extension).matches()) { if (sf_debugCheckOutput) { System.out.println("Checking .phenotype.json"); } @@ -379,7 +419,7 @@ private void checkForOutputFiles(Path dir, Path... inputFiles) throws IOExceptio checked = true; } if (extension.endsWith(".vcf") || extension.equals(BaseConfig.MATCHER_SUFFIX + ".json") || - extension.equals(BaseConfig.OUTSIDE_SUFFIX + ".tsv") || + BaseConfig.OUTSIDE_SUFFIX_PATTERN.matcher(extension).matches() || extension.equals(BaseConfig.PHENOTYPER_SUFFIX + ".json")) { if (sf_debugCheckOutput) { System.out.println("Checking .report.html"); diff --git a/src/test/java/org/pharmgkb/pharmcat/Cacna1sTest.java b/src/test/java/org/pharmgkb/pharmcat/Cacna1sTest.java index 5aac5928..814ac991 100644 --- a/src/test/java/org/pharmgkb/pharmcat/Cacna1sTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/Cacna1sTest.java @@ -48,7 +48,7 @@ void cacna1sHom_ryr1Het2(TestInfo testInfo) throws Exception { .variation("RYR1", "rs193922746", "A", "G") // c.97A>G .variation("RYR1", "rs193922749", "C", "A") // c.152C>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -81,7 +81,7 @@ void cacna1sHet_ryr1Missing(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("CACNA1S") .variation("CACNA1S", "rs772226819", "G", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("RYR1"); testWrapper.testCalledByMatcher("CACNA1S"); @@ -117,7 +117,7 @@ void cacna1sHet2_ryr1Missing(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("CACNA1S", "rs1800559", "C", "T") .variation("CACNA1S", "rs772226819", "G", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.520C>T/c.3257G>A"); @@ -155,7 +155,7 @@ void cacna1sHet_ryr1Het(TestInfo testInfo) throws Exception { .reference("RYR1") .variation("CACNA1S", "rs772226819", "G", "A") .variation("RYR1", "rs118192178", "G", "C"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -198,7 +198,7 @@ void cacna1sHet_ryr1Ref(TestInfo testInfo) throws Exception { .variation("CACNA1S", "rs772226819", "G", "A") .reference("RYR1") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); diff --git a/src/test/java/org/pharmgkb/pharmcat/DpydTest.java b/src/test/java/org/pharmgkb/pharmcat/DpydTest.java index 949287b6..5ea43b9b 100644 --- a/src/test/java/org/pharmgkb/pharmcat/DpydTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/DpydTest.java @@ -129,7 +129,7 @@ void testDpydPhased(TestInfo testInfo) throws Exception { .variation("DPYD", "rs3918290", "C", "T") .variation("DPYD", "rs1801159", "C", "T") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "DPYD"; List expectedCalls = List.of("c.1627A>G (*5)/c.1905+1G>A (*2A)"); @@ -153,7 +153,7 @@ void testDpydUnphased(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("DPYD", "rs3918290", "C", "T") .variation("DPYD", "rs1801159", "C", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.1627A>G (*5)", "c.1905+1G>A (*2A)"); RecPresence hasDpwgAnnotations = RecPresence.YES; @@ -177,7 +177,7 @@ void testDpydUndocumentedVariation(TestInfo testInfo) throws Exception { .allowUnknownAllele() .variation("DPYD", "rs3918290", "C", "G") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("Reference/Reference"); RecPresence hasDpwgAnnotations = RecPresence.YES; @@ -312,7 +312,7 @@ void testDpydUnphasedMultiple1(TestInfo testInfo) throws Exception { .variation("DPYD", "rs186169810", "A", "C") // 0.5 activity value .variation("DPYD", "rs112766203", "G", "A") // c.2279C>T - 0.5 activity value .variation("DPYD", "rs144395748", "G", "C"); // 1 activity value - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of( "c.1024G>A", @@ -343,7 +343,7 @@ void testDpydUnphasedMultiple2(TestInfo testInfo) throws Exception { .variation("DPYD", "rs67376798", "T", "A") // c.2846A>T .variation("DPYD", "rs144395748", "G", "C"); // 1 activity value - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of( "c.1024G>A", @@ -371,7 +371,7 @@ void testDpydC2846het(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .phased() .variation("DPYD", "rs67376798", "T", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("Reference/c.2846A>T"); List cpicStyleCalls = List.of("c.2846A>T (heterozygous)"); @@ -400,7 +400,7 @@ void testDpydDifferenceOnScore(TestInfo testInfo) throws Exception { highScoreWrapper.getVcfBuilder() .phased() .variation("DPYD", "rs67376798", "T", "A"); - highScoreWrapper.execute(null); + highScoreWrapper.execute(); highScoreWrapper.testCalledByMatcher("DPYD"); highScoreWrapper.testPrintCpicCalls("DPYD", "c.2846A>T (heterozygous)"); @@ -422,7 +422,7 @@ void testDpydDifferenceOnScore(TestInfo testInfo) throws Exception { lowScoreWrapper.getVcfBuilder() .phased() .variation("DPYD", "rs67376798", "A", "A"); - lowScoreWrapper.execute(null); + lowScoreWrapper.execute(); lowScoreWrapper.testCalledByMatcher("DPYD"); lowScoreWrapper.testPrintCpicCalls("DPYD", "c.2846A>T/c.2846A>T"); lowScoreWrapper.testRecommendedDiplotypes("DPYD", "c.2846A>T", "c.2846A>T"); @@ -460,7 +460,7 @@ void testDpydPhasedMultiTrans(TestInfo testInfo) throws Exception { .variation("DPYD", "rs60139309", "T", "C") // Strand 2 normal function - c.2582A>G .variation("DPYD", "rs139834141", "C", "T") // Strand 2 normal function - c.498G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("[c.498G>A + c.2582A>G]/[c.2846A>T + c.2933A>G]"); RecPresence hasDpwgAnnotations = RecPresence.NO; @@ -490,7 +490,7 @@ void testDpydUnphasedMultiTrans(TestInfo testInfo) throws Exception { .variation("DPYD", "rs60139309", "T", "C") // normal function - c.2582A>G .variation("DPYD", "rs139834141", "C", "T") // normal function - c.498G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.498G>A", "c.2582A>G", "c.2846A>T", "c.2933A>G"); RecPresence hasDpwgAnnotations = RecPresence.NO; @@ -515,7 +515,7 @@ void testDpydUnphasedMultiTrans_infer_homo(TestInfo testInfo) throws Exception { .variation("DPYD", "rs60139309", "T", "C") // normal function - c.2582A>G .variation("DPYD", "rs139834141", "C", "T") // normal function - c.498G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.498G>A", "c.2582A>G", "c.2846A>T", "c.2933A>G (homozygous)"); RecPresence hasDpwgAnnotations = RecPresence.NO; @@ -537,7 +537,7 @@ void testDpydS12het(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .phased() .variation("DPYD", "rs78060119", "C", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("Reference/c.1156G>T (*12)"); List cpicStyleCalls = List.of("c.1156G>T (*12) (heterozygous)"); @@ -561,7 +561,7 @@ void testDpydHomNoFunctionEffectivelyPhased(TestInfo testInfo) throws Exception testWrapper.getVcfBuilder() .variation("DPYD", "rs72549310", "A", "A") // c.61C>T, hom variant (No function) .variation("DPYD", "rs150385342", "C", "T"); // c.313G>A het variant (Normal function) - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.61C>T/[c.61C>T + c.313G>A]"); RecPresence hasDpwgAnnotations = RecPresence.NO; @@ -584,7 +584,7 @@ void testDpydHomNoFunctionPhased(TestInfo testInfo) throws Exception { .phased() .variation("DPYD", "rs72549310", "A", "A") // c.61C>T, hom variant (No function) .variation("DPYD", "rs150385342", "C", "T"); // c.313G>A het variant (Normal function) - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.61C>T/[c.61C>T + c.313G>A]"); RecPresence hasDpwgAnnotations = RecPresence.NO; @@ -608,7 +608,7 @@ void testDpydHomNoFunctionUnphased(TestInfo testInfo) throws Exception { .variation("DPYD", "rs67376798", "A", "T") // c.2846A>T - decreased .variation("DPYD", "rs60139309", "T", "C") // c.2582A>G - normal ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("c.2582A>G", "c.2846A>T", "c.2933A>G (homozygous)"); RecPresence hasDpwgAnnotations = RecPresence.NO; @@ -642,7 +642,7 @@ void test155(TestInfo testInfo) throws Exception { .variation("DPYD", "rs1801265", "G", "G") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of( "[c.85T>C (*9A) + c.1129-5923C>G, c.1236G>A (HapB3)]/[c.85T>C (*9A) + c.496A>G + c.1601G>A (*4)]" @@ -676,7 +676,7 @@ void test156(TestInfo testInfo) throws Exception { .variation("DPYD", "rs75017182", "C", "G") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of( "Reference/[c.1129-5923C>G, c.1236G>A (HapB3) + c.1627A>G (*5) + c.2194G>A (*6)]" @@ -710,7 +710,7 @@ void testFindCombinations(TestInfo testInfo) throws Exception { .variation("DPYD", "rs114096998", "G", "A") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of( "Reference/Reference" @@ -791,7 +791,7 @@ private void runDpydTest(TestInfo testInfo, String name, String[] data, boolean setVariation(testWrapper, vcfBuilder, "rs115232898", data[6]); assertFalse(data[7].isEmpty()); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); // 7 - phased call // 8 - phased recommendation diff --git a/src/test/java/org/pharmgkb/pharmcat/PharmCATTest.java b/src/test/java/org/pharmgkb/pharmcat/PharmCATTest.java index 8ba97152..40b53678 100644 --- a/src/test/java/org/pharmgkb/pharmcat/PharmCATTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/PharmCATTest.java @@ -5,6 +5,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.Optional; +import org.checkerframework.checker.nullness.qual.Nullable; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.junit.jupiter.api.AfterEach; @@ -15,8 +16,11 @@ import org.pharmgkb.pharmcat.haplotype.model.GeneCall; import org.pharmgkb.pharmcat.haplotype.model.Result; import org.pharmgkb.pharmcat.phenotype.Phenotyper; +import org.pharmgkb.pharmcat.reporter.MessageHelper; import org.pharmgkb.pharmcat.reporter.model.DataSource; +import org.pharmgkb.pharmcat.reporter.model.result.CallSource; import org.pharmgkb.pharmcat.reporter.model.result.GeneReport; +import org.pharmgkb.pharmcat.reporter.model.result.Haplotype; import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemOut; import static org.hamcrest.MatcherAssert.assertThat; @@ -277,7 +281,8 @@ void outsideCallsNoRecs(TestInfo testInfo) throws Exception { assertTrue(grOpt.get().isOutsideCall()); Document document = Jsoup.parse(reporterOutput.toFile()); - assertEquals(1, document.select(".gene.IFNL3_4 .alert-warning.pcat-outside-call").size()); + assertEquals(1, + document.select(".gene.IFNL3_4 .alert-warning." + MessageHelper.MSG_OUTSIDE_CALL).size()); } finally { TestUtils.deleteTestFiles(outputDir); @@ -438,6 +443,57 @@ void multisample(TestInfo testInfo) throws Exception { } } + @Test + void multipleOutsideCallFiles(TestInfo testInfo) throws Exception { + Path outsideCallFile1 = PathUtils.getPathToResource("org/pharmgkb/pharmcat/PharmCATTest-cyp2d6.tsv"); + Path outsideCallFile2 = PathUtils.getPathToResource("org/pharmgkb/pharmcat/PharmCATTest-outsideCallsNoRecs.tsv"); + Path outputDir = TestUtils.getTestOutputDir(testInfo, true); + + try { + String systemOut = tapSystemOut(() -> PharmCAT.main(new String[] { + "-phenotyper", + "-reporter", + "-reporterJson", + "-po", outsideCallFile1.toString(), + "-po", outsideCallFile2.toString(), + "-o", outputDir.toString(), + })); + assertTrue(systemOut.contains("Done.")); + + // file names should be based on the first outside call file + assertTrue(Files.exists(outputDir.resolve("PharmCATTest-cyp2d6.phenotype.json"))); + assertTrue(Files.exists(outputDir.resolve("PharmCATTest-cyp2d6.report.json"))); + assertTrue(Files.exists(outputDir.resolve("PharmCATTest-cyp2d6.report.html"))); + + // file names should NOT be based on the second outside call file + assertFalse(Files.exists(outputDir.resolve("PharmCATTest-outsideCallsNoRecs.phenotype.json"))); + assertFalse(Files.exists(outputDir.resolve("PharmCATTest-outsideCallsNoRecs.report.json"))); + assertFalse(Files.exists(outputDir.resolve("PharmCATTest-outsideCallsNoRecs.report.html"))); + + Phenotyper phenotyper = Phenotyper.read(outputDir.resolve("PharmCATTest-cyp2d6.phenotype.json")); + checkOutsideDiplotype(phenotyper.findGeneReport(DataSource.CPIC, "CYP2D6").orElse(null), + "CYP2D6*3", "CYP2D6*4"); + checkOutsideDiplotype(phenotyper.findGeneReport(DataSource.CPIC, "CYP4F2").orElse(null), + "*1", "*3"); + checkOutsideDiplotype(phenotyper.findGeneReport(DataSource.CPIC, "IFNL3").orElse(null), + "rs12979860 variant (T)", "rs12979860 variant (T)"); + + } finally { + TestUtils.deleteTestFiles(outputDir); + } + } + + public static void checkOutsideDiplotype(@Nullable GeneReport report, String allele1, String allele2) { + assertNotNull(report); + assertEquals(CallSource.OUTSIDE, report.getCallSource()); + Haplotype haplotype = report.getSourceDiplotypes().first().getAllele1(); + assertNotNull(haplotype); + assertEquals(allele1, haplotype.getName()); + haplotype = report.getSourceDiplotypes().first().getAllele2(); + assertNotNull(haplotype); + assertEquals(allele2, haplotype.getName()); + } + public static void validateCyp2d6OutsideCallOutput(Path phenotyperOutput) throws IOException { Collection reports = Phenotyper.read(phenotyperOutput).getGeneReports().get(DataSource.CPIC) diff --git a/src/test/java/org/pharmgkb/pharmcat/PipelineTest.java b/src/test/java/org/pharmgkb/pharmcat/PipelineTest.java index e172ba7a..39f08f40 100644 --- a/src/test/java/org/pharmgkb/pharmcat/PipelineTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/PipelineTest.java @@ -413,7 +413,7 @@ void testCounts(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("CYP2C9"); - testWrapper.execute(null); + testWrapper.execute(); SortedSet genes = testWrapper.getContext().getGeneReports().keySet().stream() .flatMap((k) -> testWrapper.getContext().getGeneReports().get(k).values().stream() .map(GeneReport::getGeneDisplay)) @@ -498,7 +498,7 @@ void testUndocumentedVariation(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .allowUnknownAllele() .variation("CYP2C19", "rs3758581", "G", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CYP2C19"); @@ -517,7 +517,7 @@ void testUndocumentedVariationExtendedReport(TestInfo testInfo) throws Exception testWrapper.getVcfBuilder() .allowUnknownAllele() .variation("CYP2C19", "rs3758581", "G", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CYP2C19"); @@ -540,7 +540,7 @@ void testUndocumentedVariationsWithTreatAsReference(TestInfo testInfo) throws Ex .variation("RYR1", "rs193922753", "G", "C") // not undocumented-as-reference .variation("CYP2C19", "rs3758581", "G", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List tpmtExpectedCalls = List.of("*1/*1"); List ryr1ExpectedCalls = List.of(TextConstants.HOMOZYGOUS_REFERENCE); @@ -575,7 +575,7 @@ void testUndocumentedVariationsWithTreatAsReferenceAndCombo(TestInfo testInfo) t .variation("TPMT", "rs1800462", "C", "T") // undocumented as reference + lowest-function .variation("RYR1", "rs193922753", "G", "C"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("TPMT"); testWrapper.testCalledByMatcher("RYR1"); @@ -607,7 +607,7 @@ void testUndocumentedVariationsWithTreatAsReferenceFoo(TestInfo testInfo) throws testWrapper.getVcfBuilder() .allowUnknownAllele() .variation("RYR1", "rs193922753", "G", "C"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List ryr1ExpectedCalls = List.of(TextConstants.HOMOZYGOUS_REFERENCE); @@ -636,7 +636,7 @@ void testUncallable(TestInfo testInfo) throws Exception { .variation("TPMT", "rs1256618794", "A", "A") // C -> A .variation("TPMT", "rs753545734", "C", "C") // C -> T ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = UNKNOWN_CALL; @@ -845,7 +845,7 @@ void testCyp2c19s4bs17rs28399504missing(TestInfo testInfo) throws Exception { .variation("CYP2C19", "rs12248560", "T", "T") .missing("CYP2C19", "rs28399504") .variation("CYP2C19", "rs3758581", "G", "G"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2C19"); testWrapper.testPrintCpicCalls("CYP2C19", "*4/*4", "*4/*17", "*17/*17"); @@ -961,7 +961,7 @@ void testCftrRefRef(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("CFTR"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of(TextConstants.HOMOZYGOUS_REFERENCE); @@ -982,7 +982,7 @@ void testCftrD1270NHet(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .variation("CFTR", "rs11971167", "G", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("D1270N (heterozygous)"); @@ -1003,7 +1003,7 @@ void testCftrD1270NG551D(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("CFTR", "rs11971167", "G", "A") .variation("CFTR", "rs75527207", "G", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("D1270N/G551D"); @@ -1050,7 +1050,7 @@ void testRosuvastatin(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("ABCG2", "rs2231142", "G", "T") .variation("SLCO1B1", "rs56101265", "T", "C"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("ABCG2", "SLCO1B1"); testWrapper.testPrintCpicCalls("SLCO1B1", "*1/*2"); @@ -1089,7 +1089,7 @@ void testSlco1b1HomWild(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("SLCO1B1"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("*1/*1"); @@ -1115,7 +1115,7 @@ void testSlco1b1HomVar(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("SLCO1B1", "rs2306283", "A", "G") .variation("SLCO1B1", "rs4149056", "C", "C"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("*5/*15"); @@ -1138,7 +1138,7 @@ void testSlco1b1Test5(TestInfo testInfo) throws Exception { .variation("SLCO1B1", "rs2306283", "A", "G") .variation("SLCO1B1", "rs11045852", "A", "G") .variation("SLCO1B1", "rs74064213", "A", "G"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("*1/*44"); @@ -1159,7 +1159,7 @@ void testSlco1b1Test3(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("SLCO1B1", "rs2306283", "A", "G") .variation("SLCO1B1", "rs4149056", "T", "C"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("*1/*15"); @@ -1181,7 +1181,7 @@ void testSlco1b1Test4(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("SLCO1B1", "rs4149056", "T", "C") .variation("SLCO1B1", "rs71581941", "C", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("*5/*45"); @@ -1209,7 +1209,7 @@ void testSlco1b1UncalledOverride(TestInfo testInfo) throws Exception { .variation("SLCO1B1", "rs4149056", "T", "C") .variation("SLCO1B1", "rs11045853", "A", "A") .variation("SLCO1B1", "rs72559748", "G", "G"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of("rs4149056 C/rs4149056 T"); @@ -1231,7 +1231,7 @@ void testUgt1a1Phased(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .phased() .variation("UGT1A1", "rs887829", "C", "T"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*1/*80"); @@ -1244,7 +1244,7 @@ void testUgt1a1Unphased(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .phased() .variation("UGT1A1", "rs887829", "C", "T"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*1/*80"); @@ -1256,7 +1256,7 @@ void testUgt1a1s1s1(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("UGT1A1"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*1/*1"); @@ -1269,7 +1269,7 @@ void testUgt1a1S1S80S28(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("UGT1A1", "rs887829", "C", "T") .variation("UGT1A1", "rs3064744", "TA(7)", "TA(8)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*1/*80+*28"); @@ -1281,7 +1281,7 @@ void testUgt1a1S28S37(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .variation("UGT1A1", "rs3064744", "TA(8)", "TA(9)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*28/*37"); @@ -1295,7 +1295,7 @@ void testUgt1a1s28s80phased(TestInfo testInfo) throws Exception { .phased() .variation("UGT1A1", "rs887829", "C", "T") .variation("UGT1A1", "rs3064744", "TA(7)", "TA(8)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*1/*80+*28"); @@ -1317,7 +1317,7 @@ void testUgt1a1s28s80s6s60phased(TestInfo testInfo) throws Exception { .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)") .variation("UGT1A1", "rs4148323", "G", "A"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*6/*80+*28"); @@ -1331,7 +1331,7 @@ void testUgt1a1s28s80s6s60unphased(TestInfo testInfo) throws Exception { .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)") .variation("UGT1A1", "rs4148323", "G", "A"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*6/*80+*28"); @@ -1343,7 +1343,7 @@ void testUgt1a1s6s6(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .variation("UGT1A1", "rs4148323", "A", "A"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*6/*6"); @@ -1358,7 +1358,7 @@ void testUgt1a1s6s60s80s28MissingPhased(TestInfo testInfo) throws Exception { .missing("UGT1A1", "rs3064744") .variation("UGT1A1", "rs887829", "C", "T") .variation("UGT1A1", "rs4148323", "A", "G"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*6/*80", "*6/*80+*28", "*6/*80+*37"); @@ -1375,7 +1375,7 @@ void testUgt1a1s6s60s80s28MissingUnphased(TestInfo testInfo) throws Exception { .missing("UGT1A1", "rs3064744") .variation("UGT1A1", "rs887829", "C", "T") .variation("UGT1A1", "rs4148323", "A", "G"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*6/*80", "*6/*80+*28", "*6/*80+*37"); @@ -1390,7 +1390,7 @@ void testUgt1a1s80s28missing(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .missing("UGT1A1", "rs3064744") .variation("UGT1A1", "rs887829", "C", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testRecommendedDiplotypes("UGT1A1", "*1", "*80"); @@ -1417,7 +1417,7 @@ void testUgt1a1na12717(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("UGT1A1", "rs887829", "T", "T") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*80/*80+*28"); @@ -1430,7 +1430,7 @@ void testUgt1a1s28homMissing(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .missing("UGT1A1", "rs887829") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(8)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*28/*28", "*28/*80+*28", "*80+*28/*80+*28"); @@ -1444,7 +1444,7 @@ void testUgt1a1s28s60Hom(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*1/*28"); @@ -1458,7 +1458,7 @@ void testUgt1a1s27s28unphaseds80s60missing(TestInfo testInfo) throws Exception { .missing("UGT1A1", "rs887829") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)") .variation("UGT1A1", "rs35350960", "C", "A"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testPrintCpicCalls("UGT1A1", "*27/*28", "*27/*80+*28"); @@ -1474,7 +1474,7 @@ void testUgt1a1HG00436(TestInfo testInfo) throws Exception { .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)") .variation("UGT1A1", "rs35350960", "A", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testNotCalledByMatcher("UGT1A1"); } @@ -1487,7 +1487,7 @@ void testUgt1a1s1s80s27s60s28MissingPhased(TestInfo testInfo) throws Exception { .missing("UGT1A1", "rs3064744") .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs35350960", "A", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testNotCalledByMatcher("UGT1A1"); GeneReport geneReport = testWrapper.getContext().getGeneReport(DataSource.CPIC, "UGT1A1"); @@ -1502,7 +1502,7 @@ void testUgt1a1s1s60s80s6phased(TestInfo testInfo) throws Exception { .phased() .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs35350960", "A", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testNotCalledByMatcher("UGT1A1"); GeneReport geneReport = testWrapper.getContext().getGeneReport(DataSource.CPIC, "UGT1A1"); @@ -1518,7 +1518,7 @@ void testUgt1a1s1s60s80s28s6phased(TestInfo testInfo) throws Exception { .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs3064744", "TA(8)", "TA(7)") .variation("UGT1A1", "rs35350960", "A", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testNotCalledByMatcher("UGT1A1"); GeneReport geneReport = testWrapper.getContext().getGeneReport(DataSource.CPIC, "UGT1A1"); @@ -1533,7 +1533,7 @@ void testUgt1a1s1s37s80s60phased(TestInfo testInfo) throws Exception { .phased() .variation("UGT1A1", "rs887829", "T", "C") .variation("UGT1A1", "rs3064744", "TA(9)", "TA(7)"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("UGT1A1"); testWrapper.testReportable("UGT1A1"); @@ -1549,7 +1549,7 @@ void testCyp3a5Missing3Message(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .missing("CYP3A5", "rs776746"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A5"); testWrapper.testReportable("CYP3A5"); @@ -1575,7 +1575,7 @@ void testCyp3a5v1(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .variation("CYP3A5", "rs776746", "T", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A5"); testWrapper.testReportable("CYP3A5"); @@ -1590,7 +1590,7 @@ void testCyp3a5v2(TestInfo testInfo) throws Exception { .variation("CYP3A5", "rs28383479", "C", "T") .variation("CYP3A5", "rs776746", "C", "T") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A5"); testWrapper.testPrintCpicCalls("CYP3A5", "*3/*9"); @@ -1603,7 +1603,7 @@ void testCyp3a5v3(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("CYP3A5", "rs776746", "C", "C") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A5"); testWrapper.testPrintCpicCalls("CYP3A5", "*3/*3"); @@ -1616,7 +1616,7 @@ void testCyp3a5v4(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("CYP3A5", "rs776746", "T", "C") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A5"); testWrapper.testPrintCpicCalls("CYP3A5", "*1/*3"); @@ -1630,7 +1630,7 @@ void testCyp3a5v5(TestInfo testInfo) throws Exception { .variation("CYP3A5", "rs28383479", "T", "C") .variation("CYP3A5", "rs776746", "T", "C") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A5"); testWrapper.testPrintCpicCalls("CYP3A5", "*3/*9"); @@ -1800,7 +1800,7 @@ void testTpmtStar1s(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("TPMT", "rs1800460", "C", "T") .variation("TPMT", "rs1142345", "T", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("TPMT"); testWrapper.testPrintCpicCalls("TPMT", "*1/*3A"); @@ -1818,7 +1818,7 @@ void testCyp2c9star61(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("CYP2C9", "rs1799853", "C", "T") .variation("CYP2C9", "rs202201137", "A", "G"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2C9"); testWrapper.testPrintCpicCalls("CYP2C9", "*1/*61"); @@ -1830,7 +1830,7 @@ void testCyp2c9star1Hom(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("CYP2C9"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2C9"); testWrapper.testPrintCpicCalls("CYP2C9", "*1/*1"); @@ -1857,7 +1857,7 @@ void testCyp2b6star1star34(TestInfo testInfo) throws Exception { .variation("CYP2B6", "rs3745274", "G", "T") .variation("CYP2B6", "rs2279343", "A", "G") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2B6"); testWrapper.testPrintCpicCalls("CYP2B6", "*1/*34"); @@ -1879,7 +1879,7 @@ void testCyp2b6star1star34AllMatch(TestInfo testInfo) throws Exception { .variation("CYP2B6", "rs3745274", "G", "T") .variation("CYP2B6", "rs2279343", "A", "G") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2B6"); testWrapper.testPrintCpicCalls("CYP2B6", "*1/*34", "*33/*36"); @@ -1917,7 +1917,7 @@ void testIfnl3(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("IFNL3") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("IFNL3"); testWrapper.testReportable("IFNL3"); @@ -2157,7 +2157,7 @@ void testCyp3a4(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("CYP3A4", "rs72552799", "T", "T") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP3A4"); testWrapper.testReportable("CYP3A4"); testWrapper.testPrintCalls(DataSource.DPWG, "CYP3A4", "*8/*8"); @@ -2175,7 +2175,7 @@ void testPartialCall(TestInfo testInfo) throws Exception { .variation("CYP2C19", "rs367543002", "C", "T") .variation("CYP2C19", "rs3758581", "G", "G") .missing("CYP2C19", "rs367543003"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2C19"); testWrapper.testReportable("CYP2C19"); } @@ -2214,7 +2214,7 @@ void testCyp2d6Matcher(TestInfo testInfo) throws Exception { .reference("CYP2D6") .reference("CYP2C19") .variation("CYP2C19", "rs3758581", "G", "G"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2C19", "CYP2D6"); testWrapper.testReportable("CYP2C19", "CYP2D6"); @@ -2253,6 +2253,38 @@ void testOutsideCallCollision(TestInfo testInfo) throws Exception { } + + @Test + void outsideCallCollision2Files(TestInfo testInfo) throws Exception { + + Path outsideCallPath1 = TestUtils.createTestFile(testInfo, "1.tsv"); + try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(outsideCallPath1))) { + writer.println("CYP4F2\t*1/*3"); + } + Path outsideCallPath2 = TestUtils.createTestFile(testInfo, "2.tsv"); + try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(outsideCallPath2))) { + writer.println("CYP4F2\t*9/*4"); + } + + PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); + testWrapper.getVcfBuilder() + .reference("CYP2C9"); + Path vcfFile = testWrapper.execute(outsideCallPath1, outsideCallPath2); + + // this is an outside calls + testWrapper.testNotCalledByMatcher("CYP4F2"); + // this is a regular call + testWrapper.testCalledByMatcher("CYP2C9"); + + testWrapper.testPrintCpicCalls( "CYP4F2", "*1/*3", "*4/*9"); + testWrapper.testGeneHasMessage(DataSource.CPIC, "CYP4F2", MessageHelper.MSG_OUTSIDE_CALL); + + Document document = readHtmlReport(vcfFile); + assertEquals(1, + document.select(".gene.CYP4F2 .alert-warning." + MessageHelper.MSG_OUTSIDE_CALL).size()); + } + + /** * Tests that an "unordered" diplotype should normalize to the ordered version then it can be used for matching */ @@ -2376,7 +2408,7 @@ void testWarfarinMissingRs12777823(TestInfo testInfo) throws Exception { .reference("VKORC1") .missingExtraPosition("CYP2C9", "rs12777823") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CYP2C9"); testWrapper.testReportable("CYP2C9"); @@ -2443,7 +2475,7 @@ void testDuplicateEntrySecondIsBad(TestInfo testInfo) throws Exception { .variation("NUDT15", "rs746071566", "GAGTCG(3)", "GAGTCG(4)") .duplicatePositionAsIs("NUDT15", "chr13", 48037782, "0/1", "A", "C") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("NUDT15"); testWrapper.testReportable("NUDT15"); @@ -2464,7 +2496,7 @@ void testDuplicateEntryFirstIsBad(TestInfo testInfo) throws Exception { .variationAsIs("NUDT15", "chr13", 48037782, "0/1", "A", "C") .duplicatePosition("NUDT15", "rs746071566", "GAGTCG(3)", "GAGTCG(4)") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("NUDT15"); testWrapper.testReportable("NUDT15"); diff --git a/src/test/java/org/pharmgkb/pharmcat/PipelineWrapper.java b/src/test/java/org/pharmgkb/pharmcat/PipelineWrapper.java index a1418e9c..e406c179 100644 --- a/src/test/java/org/pharmgkb/pharmcat/PipelineWrapper.java +++ b/src/test/java/org/pharmgkb/pharmcat/PipelineWrapper.java @@ -13,6 +13,7 @@ import java.util.TreeSet; import java.util.stream.Collectors; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.jupiter.api.TestInfo; @@ -101,11 +102,14 @@ TestVcfBuilder getVcfBuilder() { return m_vcfBuilder; } - @Nullable Path execute(Path outsideCallPath) throws Exception { - return execute(outsideCallPath, false); + @Nullable Path execute(Path... outsideCallPath) throws Exception { + if (outsideCallPath == null || outsideCallPath.length == 0) { + return execute(null, false); + } + return execute(ImmutableList.copyOf(outsideCallPath), false); } - @Nullable Path execute(Path outsideCallPath, boolean allowNoData) throws Exception { + @Nullable Path execute(@Nullable List outsideCallPaths, boolean allowNoData) throws Exception { Path vcfFile = null; VcfFile vcfFileObj = null; boolean runMatcher = false; @@ -117,7 +121,7 @@ TestVcfBuilder getVcfBuilder() { Pipeline pcat = new Pipeline(m_env, runMatcher, vcfFileObj, null, true, m_topCandidatesOnly, m_callCyp2d6, m_findCombinations, true, - true, null, outsideCallPath, + true, null, outsideCallPaths, true, null, null, m_sources, m_compactReport, true, true, m_outputPath, null, m_compactReport, Pipeline.Mode.TEST, null, false diff --git a/src/test/java/org/pharmgkb/pharmcat/Ryr1Test.java b/src/test/java/org/pharmgkb/pharmcat/Ryr1Test.java index 2403c49e..151d9809 100644 --- a/src/test/java/org/pharmgkb/pharmcat/Ryr1Test.java +++ b/src/test/java/org/pharmgkb/pharmcat/Ryr1Test.java @@ -48,7 +48,7 @@ void cacna1sRef_ryr1Undocumented(TestInfo testInfo) throws Exception { .reference("CACNA1S") .reference("RYR1") .variation("RYR1", "rs193922749", "A", "T"); // c.152C>A - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -80,7 +80,7 @@ void cacna1sRef_ryr1Het(TestInfo testInfo) throws Exception { .reference("CACNA1S") .reference("RYR1") .variation("RYR1", "rs193922749", "A", "C"); // c.152C>A - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -114,7 +114,7 @@ void cacna1sRef_ryr1Het2(TestInfo testInfo) throws Exception { .variation("RYR1", "rs34694816", "A", "G") .variation("RYR1", "rs137933390", "A", "G") ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -143,7 +143,7 @@ void cacna1sRef_ryr1Het3(TestInfo testInfo) throws Exception { .variation("RYR1", "rs137933390", "A", "G") // c.4178A>G, normal .variation("RYR1", "rs145573319", "A", "G") // c.4400A>G, uncertain ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -165,7 +165,7 @@ void cacna1sMissing_ryr1Ref(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("RYR1"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("RYR1"); @@ -200,7 +200,7 @@ void cacna1sMissing_ryr1Het(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("RYR1") .variation("RYR1", "rs118192178", "C", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -232,7 +232,7 @@ void cacna1sMissing_ryr1Het2(TestInfo testInfo) throws Exception { .variation("RYR1", "rs34694816", "A", "G") .variation("RYR1", "rs137933390", "A", "G") // c.4178A>G ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -266,7 +266,7 @@ void cacna1sMissing_ryr1Het1Hom1(TestInfo testInfo) throws Exception { .variation("RYR1", "rs193922746", "A", "G") // c.97A>G - malignant .variation("RYR1", "rs142474192", "A", "A") // c.418G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -294,7 +294,7 @@ void cacna1sMissing_ryr1Het2Hom1(TestInfo testInfo) throws Exception { .variation("RYR1", "rs193922749", "C", "A") // c.152C>A .variation("RYR1", "rs142474192", "G", "A") // c.418G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -323,7 +323,7 @@ void cacna1sMissing_ryr1Het2Hom1Phased(TestInfo testInfo) throws Exception { .variation("RYR1", "rs193922749", "C", "A") // c.152C>A .variation("RYR1", "rs142474192", "G", "A") // c.418G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -351,7 +351,7 @@ void cacna1sMissing_ryr1Het3(TestInfo testInfo) throws Exception { .variation("RYR1", "rs193922749", "C", "A") // c.152C>A .variation("RYR1", "rs142474192", "G", "A") // c.418G>A ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -381,7 +381,7 @@ void cacna1sMissing_ryr1Het4(TestInfo testInfo) throws Exception { .variation("RYR1", "rs142474192", "G", "A") // c.418G>A .variation("RYR1", "rs146876145", "C", "T") // c.14918C>T - malignant ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); @@ -413,7 +413,7 @@ void cacna1sMissing_ryr1Het4Phased(TestInfo testInfo) throws Exception { .variation("RYR1", "rs142474192", "G", "A") // c.418G>A .variation("RYR1", "rs146876145", "C", "T") // c.14918C>T - malignant ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testNotCalledByMatcher("CACNA1S"); testWrapper.testCalledByMatcher("RYR1"); diff --git a/src/test/java/org/pharmgkb/pharmcat/SyntheticBatchTest.java b/src/test/java/org/pharmgkb/pharmcat/SyntheticBatchTest.java index 99cb058c..1480cce4 100644 --- a/src/test/java/org/pharmgkb/pharmcat/SyntheticBatchTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/SyntheticBatchTest.java @@ -6,9 +6,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.text.SimpleDateFormat; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.stream.Collectors; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import org.checkerframework.checker.nullness.qual.Nullable; import org.junit.platform.launcher.Launcher; @@ -108,6 +110,9 @@ private static void doRun(@Nullable Path dir, boolean compact, List if (dir != null) { System.out.println("Saving results to " + dir); TestUtils.setTestOutputDir(dir); + if (!Files.exists(dir)) { + Files.createDirectories(dir); + } } TestUtils.setSaveTestOutput(true); @@ -552,19 +557,20 @@ private SyntheticBatchTest(boolean compact, List sources) throws IOE Files.writeString(TestUtils.createTestFile(getClass(), "README.md"), readmeContent); } - private void makeReport(String key, String[] testVcfs, Path outsideCallPath) throws Exception { + private void makeReport(String key, String[] testVcfs, @Nullable Path outsideCallPath) throws Exception { Path testDir = TestUtils.getTestOutputDir(getClass(), false); if (!Files.exists(testDir)) { if (!testDir.toFile().mkdirs()) { throw new RuntimeException("Output directory could not be created " + testDir.toAbsolutePath()); } } + List outsideCallPaths = outsideCallPath == null ? Collections.emptyList() : ImmutableList.of(outsideCallPath); Path sampleVcf = writeVcf(testDir.resolve(key + ".vcf"), testVcfs); new Pipeline(new Env(), true, new VcfFile(sampleVcf), null, true, true, false, false, true, - true, null, outsideCallPath, + true, null, outsideCallPaths, true, null, null, m_sources, m_compact, false, true, testDir, null, m_compact, Pipeline.Mode.TEST, null, false diff --git a/src/test/java/org/pharmgkb/pharmcat/ToxicGenesTest.java b/src/test/java/org/pharmgkb/pharmcat/ToxicGenesTest.java index 2de616d4..16bd96bd 100644 --- a/src/test/java/org/pharmgkb/pharmcat/ToxicGenesTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/ToxicGenesTest.java @@ -53,7 +53,7 @@ void testUncallable_partial_haplotype(TestInfo testInfo) throws Exception { .variation("TPMT", "rs1256618794", "C", "A") // C -> A .variation("TPMT", "rs753545734", "C", "C") // C -> T ; - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = UNKNOWN_CALL; @@ -79,7 +79,7 @@ void cacna1sRef_ryr1Ref(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("CACNA1S") .reference("RYR1"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); List expectedCalls = List.of(TextConstants.HOMOZYGOUS_REFERENCE); @@ -112,7 +112,7 @@ void testG6pdRef_male(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .male() .reference("G6PD"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("G6PD"); testWrapper.testReportable("G6PD"); @@ -131,7 +131,7 @@ void testG6pd_Ref_female(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .female() .reference("G6PD"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("G6PD"); testWrapper.testReportable("G6PD"); @@ -151,7 +151,7 @@ void testG6pd_MDPSCB_male(TestInfo testInfo) throws Exception { .male() .reference("G6PD") .variation("G6PD", "rs5030868", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "G6PD"; List expectedCalls = List.of("Mediterranean, Dallas, Panama, Sassari, Cagliari, Birmingham"); @@ -172,7 +172,7 @@ void testG6pd_MDPSCB_female_homo(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("G6PD") .variation("G6PD", "rs5030868", "A", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "G6PD"; List expectedCalls = List.of("Mediterranean, Dallas, Panama, Sassari, Cagliari, Birmingham/Mediterranean, Dallas, Panama, Sassari, Cagliari, Birmingham"); @@ -193,7 +193,7 @@ void testG6pd_MDPSCB_female_het(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("G6PD") .variation("G6PD", "rs5030868", "G", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "G6PD"; List expectedCalls = List.of("B (reference)/Mediterranean, Dallas, Panama, Sassari, Cagliari, Birmingham"); @@ -216,7 +216,7 @@ void testG6pd_chatham_male(TestInfo testInfo) throws Exception { .male() .reference("G6PD") .variation("G6PD", "rs5030869", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "G6PD"; List expectedCalls = List.of("Chatham"); @@ -237,7 +237,7 @@ void testG6pd_chatham_female_homo(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("G6PD") .variation("G6PD", "rs5030869", "T", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "G6PD"; List expectedCalls = List.of("Chatham/Chatham"); @@ -258,7 +258,7 @@ void testG6pd_chatham_female_het(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .reference("G6PD") .variation("G6PD", "rs5030869", "C", "T"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); String gene = "G6PD"; List expectedCalls = List.of("B (reference)/Chatham"); @@ -280,7 +280,7 @@ void testG6pd_Arakawa_male(TestInfo testInfo) throws Exception { .male() .reference("G6PD") .variation("G6PD", "chrX", 154532082, "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("G6PD"); testWrapper.testReportable("G6PD"); @@ -300,7 +300,7 @@ void testG6pd_Arakawa_female_het(TestInfo testInfo) throws Exception { .female() .reference("G6PD") .variation("G6PD", "chrX", 154532082, "G", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("G6PD"); testWrapper.testReportable("G6PD"); @@ -320,7 +320,7 @@ void testG6pd_Arakawa_female_homo(TestInfo testInfo) throws Exception { .female() .reference("G6PD") .variation("G6PD", "chrX", 154532082, "A", "A"); - Path vcfFile = testWrapper.execute(null); + Path vcfFile = testWrapper.execute(); testWrapper.testCalledByMatcher("G6PD"); testWrapper.testReportable("G6PD"); @@ -339,7 +339,7 @@ void testNudt15Ref(TestInfo testInfo) throws Exception { PipelineWrapper testWrapper = new PipelineWrapper(testInfo, false); testWrapper.getVcfBuilder() .reference("NUDT15"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testPrintCpicCalls("NUDT15", "*1/*1"); testWrapper.testRecommendedDiplotypes("NUDT15", "*1", "*1"); @@ -360,7 +360,7 @@ void testNudt15S2(TestInfo testInfo) throws Exception { .variation("NUDT15", "rs746071566", "GAGTCG(3)", "GAGTCG(4)") .variation("NUDT15", "rs116855232", "C", "T") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("NUDT15"); testWrapper.testPrintCpicCalls("NUDT15", "*1/*2"); @@ -381,7 +381,7 @@ void testNudt15S3(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("NUDT15", "rs116855232", "C", "T") ; - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("NUDT15"); testWrapper.testPrintCpicCalls("NUDT15", "*1/*3"); @@ -399,7 +399,7 @@ void testTpmtStar1s(TestInfo testInfo) throws Exception { testWrapper.getVcfBuilder() .variation("TPMT", "rs1800460", "C", "T") .variation("TPMT", "rs1142345", "T", "C"); - testWrapper.execute(null); + testWrapper.execute(); testWrapper.testCalledByMatcher("TPMT"); testWrapper.testPrintCpicCalls("TPMT", "*1/*3A"); diff --git a/src/test/java/org/pharmgkb/pharmcat/phenotype/PhenotyperTest.java b/src/test/java/org/pharmgkb/pharmcat/phenotype/PhenotyperTest.java index 0a7e7559..1b8520c2 100644 --- a/src/test/java/org/pharmgkb/pharmcat/phenotype/PhenotyperTest.java +++ b/src/test/java/org/pharmgkb/pharmcat/phenotype/PhenotyperTest.java @@ -6,6 +6,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.function.Supplier; @@ -96,7 +97,7 @@ void testCyp2D6Only() throws Exception { void testCyp2C19Hom() throws Exception { Phenotyper phenotyper = new Phenotyper(s_env, readMatchData("Cyp2C19s2s2.match.json"), - new ArrayList<>(), null); + new HashSet<>(), null); assertCalledByMatcher(phenotyper, "CYP2C19"); @@ -107,7 +108,7 @@ void testCyp2C19Hom() throws Exception { void testUGT1A1Phased() throws Exception { Phenotyper phenotyper = new Phenotyper(s_env, readMatchData("UGT1A1s1s60s80phased.match.json"), - new ArrayList<>(), null); + new HashSet<>(), null); assertCalledByMatcher(phenotyper, "UGT1A1"); @@ -120,7 +121,7 @@ void testUGT1A1Phased() throws Exception { void testUGT1A1Unphased() throws Exception { Phenotyper phenotyper = new Phenotyper(s_env, readMatchData("UGT1A1s1s60s80unphased.match.json"), - new ArrayList<>(), null); + new HashSet<>(), null); assertCalledByMatcher(phenotyper, "UGT1A1"); @@ -133,7 +134,7 @@ void testUGT1A1Unphased() throws Exception { void testNUDT15() throws Exception { Phenotyper phenotyper = new Phenotyper(s_env, readMatchData("NUDT15ref.match.json"), - new ArrayList<>(), null); + new HashSet<>(), null); assertCalledByMatcher(phenotyper, "NUDT15"); @@ -145,7 +146,7 @@ void testNUDT15() throws Exception { void testNUDT15star3() throws Exception { Phenotyper phenotyper = new Phenotyper(s_env, readMatchData("NUDT15s3.match.json"), - new ArrayList<>(), null); + new HashSet<>(), null); assertCalledByMatcher(phenotyper, "NUDT15");