From 8d0a4168c8b07c0141b15d2b34bd1307e7324eaa Mon Sep 17 00:00:00 2001 From: Megan Shand Date: Tue, 14 May 2024 15:22:01 -0400 Subject: [PATCH 1/4] adding arg to variant filtration to write your own description in VCFHeader --- .../walkers/filters/VariantFiltration.java | 12 +++++++++++- .../VariantFiltrationIntegrationTest.java | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java index dd6a2e93838..9d09b7245e6 100644 --- a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java +++ b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java @@ -114,6 +114,7 @@ public final class VariantFiltration extends VariantWalker { public static final String CLUSTER_WINDOW_SIZE_LONG_NAME = "cluster-window-size"; public static final String MASK_EXTENSION_LONG_NAME = "mask-extension"; public static final String MASK_NAME_LONG_NAME = "mask-name"; + public static final String MASK_DESCRIPTION_LONG_NAME = "mask-desc"; public static final String FILTER_NOT_IN_MASK_LONG_NAME = "filter-not-in-mask"; public static final String MISSING_VAL_LONG_NAME = "missing-values-evaluate-as-failing"; public static final String INVERT_LONG_NAME = "invert-filter-expression"; @@ -238,6 +239,13 @@ public final class VariantFiltration extends VariantWalker { @Argument(fullName=ALLELE_SPECIFIC_LONG_NAME, optional=true, doc="Set mask at the allele level. This option is not compatible with clustering.") public boolean applyForAllele = false; + /** + * If a mask interval list is provided, then set the description of the filter in the VCF header to this String. + * Note that if spaces are needed, then the entire description should be enclosed in quotes. + */ + @Argument(fullName=MASK_DESCRIPTION_LONG_NAME, optional=true, doc="Description to add to the FILTER field in VCF header for the mask filter.") + public String maskDescription; + // JEXL expressions for the filters private List filterExps; private List genotypeFilterExps; @@ -305,7 +313,9 @@ private void initializeVcfWriter() { } if ( mask != null ) { - if (filterRecordsNotInMask) { + if (maskDescription != null) { + hInfo.add(new VCFFilterHeaderLine(maskName, maskDescription)); + } else if (filterRecordsNotInMask) { hInfo.add(new VCFFilterHeaderLine(maskName, "Doesn't overlap a user-input mask")); } else { hInfo.add(new VCFFilterHeaderLine(maskName, "Overlaps a user-input mask")); diff --git a/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java b/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java index c6e8851a096..bd5e440a4bd 100644 --- a/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java +++ b/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java @@ -1,12 +1,14 @@ package org.broadinstitute.hellbender.tools.walkers.filters; import htsjdk.variant.variantcontext.VariantContext; +import htsjdk.variant.vcf.VCFHeader; import org.broadinstitute.hellbender.CommandLineProgramTest; import org.broadinstitute.hellbender.cmdline.StandardArgumentDefinitions; import org.broadinstitute.hellbender.engine.FeatureDataSource; import org.broadinstitute.hellbender.exceptions.UserException; import org.broadinstitute.hellbender.testutils.ArgumentsBuilder; import org.broadinstitute.hellbender.testutils.IntegrationTestSpec; +import org.broadinstitute.hellbender.testutils.VariantContextTestUtils; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -91,6 +93,22 @@ public void testMaskReversed() throws IOException { spec.executeTest("testMaskReversed", this); } + @Test + public void testMaskDescription() throws IOException { + final File output = createTempFile("testHeader", ".vcf"); + + final ArgumentsBuilder args = new ArgumentsBuilder(); + args.add("V", getTestFile("vcfexample2.vcf")) + .add("mask-name", "foo") + .add("mask-desc", "description") + .add("mask:BED", getToolTestDataDir() + "goodMask.bed"); + args.addOutput(output); + + runCommandLine(args); + VCFHeader header = VariantContextTestUtils.getVCFHeader(output.getAbsolutePath()); + header.getFilterLines().stream().filter(f -> f.getID().equals("foo")).forEach(f -> Assert.assertEquals(f.getDescription(), "description")); + } + @Test public void testIllegalFilterName() throws IOException { final IntegrationTestSpec spec = new IntegrationTestSpec( From d8750e0bfccbf2c907cbba514e050b492cdbbc6c Mon Sep 17 00:00:00 2001 From: Megan Shand Date: Tue, 14 May 2024 15:26:40 -0400 Subject: [PATCH 2/4] doc --- .../hellbender/tools/walkers/filters/VariantFiltration.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java index 9d09b7245e6..a79f7d4ae2d 100644 --- a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java +++ b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java @@ -241,7 +241,8 @@ public final class VariantFiltration extends VariantWalker { /** * If a mask interval list is provided, then set the description of the filter in the VCF header to this String. - * Note that if spaces are needed, then the entire description should be enclosed in quotes. + * Note that if spaces are needed, then the entire description should be enclosed in quotes. Also note that if + * --filter-not-in-mask is used, the description should be adapted to reflect the reverse logic. */ @Argument(fullName=MASK_DESCRIPTION_LONG_NAME, optional=true, doc="Description to add to the FILTER field in VCF header for the mask filter.") public String maskDescription; From 032418b3f91d88ff3f587f3775e975ae643b20cc Mon Sep 17 00:00:00 2001 From: Megan Shand Date: Tue, 14 May 2024 15:31:47 -0400 Subject: [PATCH 3/4] arg check --- .../hellbender/tools/walkers/filters/VariantFiltration.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java index a79f7d4ae2d..84441005cd2 100644 --- a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java +++ b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java @@ -342,6 +342,9 @@ public void onTraversalStart() { if (filterRecordsNotInMask && mask == null) { throw new CommandLineException.BadArgumentValue(FILTER_NOT_IN_MASK_LONG_NAME, "argument not allowed if mask argument is not provided"); } + if (maskDescription != null && mask == null) { + throw new CommandLineException.BadArgumentValue(MASK_DESCRIPTION_LONG_NAME, "argument not allowed if mask argument is not provided"); + } filterExps = VariantContextUtils.initializeMatchExps(filterNames, filterExpressions); genotypeFilterExps = VariantContextUtils.initializeMatchExps(genotypeFilterNames, genotypeFilterExpressions); howToTreatMissingValues = failMissingValues ? JexlMissingValueTreatment.TREAT_AS_MATCH : JexlMissingValueTreatment.TREAT_AS_MISMATCH; From 4babf10bd2f55aab2b6e6c7bc5c4cc0a45550e0e Mon Sep 17 00:00:00 2001 From: Megan Shand Date: Wed, 15 May 2024 14:44:08 -0400 Subject: [PATCH 4/4] better arg name --- .../hellbender/tools/walkers/filters/VariantFiltration.java | 2 +- .../tools/walkers/filters/VariantFiltrationIntegrationTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java index 84441005cd2..a2642f20150 100644 --- a/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java +++ b/src/main/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltration.java @@ -114,7 +114,7 @@ public final class VariantFiltration extends VariantWalker { public static final String CLUSTER_WINDOW_SIZE_LONG_NAME = "cluster-window-size"; public static final String MASK_EXTENSION_LONG_NAME = "mask-extension"; public static final String MASK_NAME_LONG_NAME = "mask-name"; - public static final String MASK_DESCRIPTION_LONG_NAME = "mask-desc"; + public static final String MASK_DESCRIPTION_LONG_NAME = "mask-description"; public static final String FILTER_NOT_IN_MASK_LONG_NAME = "filter-not-in-mask"; public static final String MISSING_VAL_LONG_NAME = "missing-values-evaluate-as-failing"; public static final String INVERT_LONG_NAME = "invert-filter-expression"; diff --git a/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java b/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java index bd5e440a4bd..d5466ef905d 100644 --- a/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java +++ b/src/test/java/org/broadinstitute/hellbender/tools/walkers/filters/VariantFiltrationIntegrationTest.java @@ -100,7 +100,7 @@ public void testMaskDescription() throws IOException { final ArgumentsBuilder args = new ArgumentsBuilder(); args.add("V", getTestFile("vcfexample2.vcf")) .add("mask-name", "foo") - .add("mask-desc", "description") + .add("mask-description", "description") .add("mask:BED", getToolTestDataDir() + "goodMask.bed"); args.addOutput(output);