diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ce7bc34..981afdfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### `Added` +- [#215](https://github.com/IntGenomicsLab/lrsomatic/pull/215) - Added optional whitelist SV calling: `SEVERUS` now runs a patched Severus 1.7 image (`oras://docker.io/amberverhasselt/severus-sif:1.7-whitelist-6813dee`), whose output without a whitelist is identical to stock 1.7, and takes an optional whitelist BED: `--severus_whitelist ` reports every SV inside the whitelisted regions, past the read-quality, minimum-support and VNTR filters, with corroboration required for single-read junctions. Extra flags go through `--severus_whitelist_args`. `--severus_whitelist` is not supported under Conda (@AmberVerhasselt). - [#197](https://github.com/IntGenomicsLab/lrsomatic/pull/197) - Added CHM13 support for ClairS-TO's Verdict module, which tags tumour-only calls as germline, somatic or subclonal somatic; its resources were GRCh38-only, so on CHM13 germline variants leaked into `somatic.vcf.gz`. With `--genome CHM13 --skip_ascat` the pipeline builds a CHM13 resource set from the ASCAT files it already downloads and passes it as `--cna_resource_dir`; a prepared directory can be given with `--clairsto_cna_resources` (validated at launch). Without `--skip_ascat` tagging comes from ASCAT's own tables instead (next entry) (@ljwharbers). - [#197](https://github.com/IntGenomicsLab/lrsomatic/pull/197) - Added `CLAIRSTO_VERDICT_TAG`: when ASCAT is in the run, Verdict's germline tagging is computed from ASCAT's purity, ploidy and segments instead of Verdict's own estimate, so `CLAIRSTO` runs with `--disable_verdict` and ASCAT runs before small variant calling. Output names are unchanged. The tables the tags were computed from are published as `_Tumor_Purity_Ploidy.txt` and `_Tumor_CNA.txt`, also on `--skip_ascat` runs (@ljwharbers). - [#197](https://github.com/IntGenomicsLab/lrsomatic/pull/197) - Added a stub nf-test for `TUMORONLY_SMALLVAR` covering both germline tagging paths (tag `small`) (@ljwharbers). diff --git a/conf/modules.config b/conf/modules.config index 8e0b2b96..b5d54771 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -533,7 +533,7 @@ process { withName: '.*:SEVERUS' { ext.prefix = "." - ext.args = { "--min-support ${params.severus_minsupport} --output-read-ids " } + ext.args = { "--min-support ${params.severus_minsupport} --output-read-ids ${params.severus_whitelist ? (params.severus_whitelist_args ?: '') : ''}" } publishDir = [ path: { "${params.outdir}/${meta.id}/variants/severus" }, mode: params.publish_dir_mode, diff --git a/docs/output.md b/docs/output.md index 2f1a8828..ff1620da 100644 --- a/docs/output.md +++ b/docs/output.md @@ -376,6 +376,8 @@ The germline/somatic split comes from a panel of normals and from ClairS-TO's Ve | `read_qual.txt` | file containing quality statistics about identified segements | | `severus.log` | log file | +With `--severus_whitelist` the same files are published here. Passing `--write-alignments` through `--severus_whitelist_args` adds a `read_alignments` file. + #### `savana` SAVANA structural variant and copy-number calling. Runs alongside Severus/ASCAT rather than replacing diff --git a/docs/usage.md b/docs/usage.md index 7994301a..0a3b0222 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -285,9 +285,13 @@ opt-in. See [VEP plugins](#vep-plugins) for sizes, licence terms and per-assembl #### SEVERUS Options -| Parameter | Description | -| ---------------------- | ------------------------------------------------------------------------------------ | -| `--severus_minsupport` | Minimum number of supporting reads required for SEVERUS to call an SV. Default = `3` | +| Parameter | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `--severus_minsupport` | Minimum number of supporting reads required for SEVERUS to call an SV. Default = `3` | +| `--severus_whitelist` | BED file of regions in which every SV is reported (Severus `--whitelist`). Passed to `SEVERUS` as `--whitelist`; its VCFs feed SV VEP, Wakhan and the report as usual. Default = off | +| `--severus_whitelist_args` | Extra arguments for `SEVERUS`, only used with `--severus_whitelist`, e.g. `--whitelist-single-read any`, `--whitelist-allow-intra-region` or `--write-alignments`. Default = none | + +`SEVERUS` runs a patched Severus 1.7 build ([AmberVerhasselt/Severus](https://github.com/AmberVerhasselt/Severus/tree/whitelist-reciprocal-corroboration)) from `oras://docker.io/amberverhasselt/severus-sif` (`docker.io/amberverhasselt/severus` under Docker); without `--severus_whitelist` its output is identical to stock Severus 1.7. Inside the whitelisted regions it skips the read-quality, minimum-support and VNTR filters, and keeps a junction supported by a single read only when a reciprocal or independently supported junction corroborates it. This is meant for loci such as the IG and TCR genes, where translocations are often carried by few, divergent reads. **`--severus_whitelist` is not supported under Conda**, which installs stock Severus. #### SAVANA Options diff --git a/modules/nf-core/severus/main.nf b/modules/nf-core/severus/main.nf index f37891c7..430d7cde 100644 --- a/modules/nf-core/severus/main.nf +++ b/modules/nf-core/severus/main.nf @@ -3,13 +3,18 @@ process SEVERUS { label 'process_medium' conda "${moduleDir}/environment.yml" + // Patched Severus 1.7 (github.com/AmberVerhasselt/Severus/tree/whitelist-reciprocal-corroboration, 6813dee) carries the --whitelist fixes; + // without --whitelist its VCF records are identical to stock 1.7 (the header adds a WL_RESCUE INFO line). Revert to the biocontainer once + // KolmogorovLab/Severus carries the fixes. + // Conda installs stock bioconda Severus, so --severus_whitelist is refused under conda at startup (utils_nfcore_lrsomatic_pipeline). container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8f/8fd0858ee067f8b95246e57683a7431bc126929b4203fbda8e315cd94d2570ad/data': - 'community.wave.seqera.io/library/severus:1.7--d16d59609ef4ee7d' }" + 'oras://docker.io/amberverhasselt/severus-sif:1.7-whitelist-6813dee': + 'docker.io/amberverhasselt/severus:1.7-whitelist-6813dee' }" input: tuple val(meta), path(target_input), path(target_index), path(control_input), path(control_index), path(vcf), path(tbi) tuple val(meta2), path(bed), path(pon_path) + tuple val(meta3), path(whitelist) output: tuple val(meta), path("${prefix}/severus.log") , emit: log @@ -39,6 +44,7 @@ process SEVERUS { def vntr_bed = bed ? "--vntr-bed ${bed}" : "" def phasing_vcf = vcf ? "--phasing-vcf ${vcf}" : "" def pon = pon_path && (!control_input) ? "--PON ${pon_path}" : "" + def whitelist_bed = whitelist ? "--whitelist ${whitelist}" : "" """ severus \\ @@ -49,6 +55,7 @@ process SEVERUS { $pon \\ $control \\ $phasing_vcf \\ + $whitelist_bed \\ --out-dir ${prefix} bgzip ${prefix}/somatic_SVs/severus_somatic.vcf diff --git a/modules/nf-core/severus/meta.yml b/modules/nf-core/severus/meta.yml index f03b19cd..80c8c559 100644 --- a/modules/nf-core/severus/meta.yml +++ b/modules/nf-core/severus/meta.yml @@ -51,6 +51,11 @@ input: specific SV calling pattern: "*.{vcf,vcf.gz}" ontologies: [] + - tbi: + type: file + description: index of the phasing vcf + pattern: "*.tbi" + ontologies: [] - - meta2: type: map description: | @@ -61,6 +66,22 @@ input: description: path to bed file for tandem repeat regions (must be ordered) pattern: "*.bed" ontologies: [] + - pon_path: + type: file + description: panel of normals, passed as --PON for tumour-only samples only + pattern: "*.tsv.gz" + ontologies: [] + - - meta3: + type: map + description: | + Groovy Map containing whitelist information + e.g. `[:]` + - whitelist: + type: file + description: optional bed file of regions in which every SV is reported (--whitelist); + needs the patched Severus image + pattern: "*.bed" + ontologies: [] output: log: - - meta: @@ -144,33 +165,33 @@ output: type: map description: | Groovy Map containing sample information - - ${prefix}/all_SVs/severus_all.vcf: - type: map + - ${prefix}/all_SVs/severus_all.vcf.gz: + type: file description: | - VCF file containing somatic and germline structural variants - pattern: "${prefix}/all_SVs/severus_all.vcf" + bgzipped VCF file containing somatic and germline structural variants + pattern: "${prefix}/all_SVs/severus_all.vcf.gz" ontologies: [] all_breakpoints_clusters_list: - - meta: type: map description: | Groovy Map containing sample information - - ${prefix}/all_SVs/breakpoints_clusters_list.tsv: + - ${prefix}/all_SVs/breakpoint_clusters_list.tsv: type: file description: | a TSV containing a list of all breakpoint clusters - pattern: "${prefix}/all_SVs/breakpoints_clusters_list.tsv" + pattern: "${prefix}/all_SVs/breakpoint_clusters_list.tsv" ontologies: [] all_breakpoints_clusters: - - meta: type: map description: | Groovy Map containing sample information - - ${prefix}/all_SVs/breakpoints_clusters.tsv: + - ${prefix}/all_SVs/breakpoint_clusters.tsv: type: file description: | TSV file listing meta information in breakpoint clusters - pattern: "${prefix}/all_SVs/breakpoints_clusters.tsv" + pattern: "${prefix}/all_SVs/breakpoint_clusters.tsv" ontologies: [] all_plots: - - meta: @@ -188,33 +209,33 @@ output: type: map description: | Groovy Map containing sample information - - ${prefix}/somatic_SVs/severus_somatic.vcf: + - ${prefix}/somatic_SVs/severus_somatic.vcf.gz: type: file description: | - VCF file containing somatic structural variants (SV) - pattern: "${prefix}/somatic_SVs/severus_all.vcf" + bgzipped VCF file containing somatic structural variants (SV) + pattern: "${prefix}/somatic_SVs/severus_somatic.vcf.gz" ontologies: [] somatic_breakpoints_clusters_list: - - meta: type: map description: | Groovy Map containing sample information - - ${prefix}/somatic_SVs/breakpoints_clusters_list.tsv: + - ${prefix}/somatic_SVs/breakpoint_clusters_list.tsv: type: file description: | TSV file containing full list of somatic breakpoint clusters - pattern: "${prefix}/somatic_SVs/breakpoints_clusters_list.tsv" + pattern: "${prefix}/somatic_SVs/breakpoint_clusters_list.tsv" ontologies: [] somatic_breakpoints_clusters: - - meta: type: map description: | Groovy Map containing sample information - - ${prefix}/somatic_SVs/breakpoints_clusters.tsv: + - ${prefix}/somatic_SVs/breakpoint_clusters.tsv: type: file description: | TSV file containing meta information of somatic breakpoint clusters - pattern: "${prefix}/somatic_SVs/breakpoints_clusters.tsv" + pattern: "${prefix}/somatic_SVs/breakpoint_clusters.tsv" ontologies: [] somatic_plots: - - meta: diff --git a/modules/nf-core/severus/severus.diff b/modules/nf-core/severus/severus.diff index 133f591c..3c405689 100644 --- a/modules/nf-core/severus/severus.diff +++ b/modules/nf-core/severus/severus.diff @@ -1,21 +1,154 @@ Changes in component 'nf-core/severus' 'modules/nf-core/severus/environment.yml' is unchanged -'modules/nf-core/severus/meta.yml' is unchanged +Changes in 'severus/meta.yml': +--- modules/nf-core/severus/meta.yml ++++ modules/nf-core/severus/meta.yml +@@ -51,6 +51,11 @@ + specific SV calling + pattern: "*.{vcf,vcf.gz}" + ontologies: [] ++ - tbi: ++ type: file ++ description: index of the phasing vcf ++ pattern: "*.tbi" ++ ontologies: [] + - - meta2: + type: map + description: | +@@ -61,6 +66,22 @@ + description: path to bed file for tandem repeat regions (must be ordered) + pattern: "*.bed" + ontologies: [] ++ - pon_path: ++ type: file ++ description: panel of normals, passed as --PON for tumour-only samples only ++ pattern: "*.tsv.gz" ++ ontologies: [] ++ - - meta3: ++ type: map ++ description: | ++ Groovy Map containing whitelist information ++ e.g. `[:]` ++ - whitelist: ++ type: file ++ description: optional bed file of regions in which every SV is reported (--whitelist); ++ needs the patched Severus image ++ pattern: "*.bed" ++ ontologies: [] + output: + log: + - - meta: +@@ -144,33 +165,33 @@ + type: map + description: | + Groovy Map containing sample information +- - ${prefix}/all_SVs/severus_all.vcf: +- type: map ++ - ${prefix}/all_SVs/severus_all.vcf.gz: ++ type: file + description: | +- VCF file containing somatic and germline structural variants +- pattern: "${prefix}/all_SVs/severus_all.vcf" ++ bgzipped VCF file containing somatic and germline structural variants ++ pattern: "${prefix}/all_SVs/severus_all.vcf.gz" + ontologies: [] + all_breakpoints_clusters_list: + - - meta: + type: map + description: | + Groovy Map containing sample information +- - ${prefix}/all_SVs/breakpoints_clusters_list.tsv: ++ - ${prefix}/all_SVs/breakpoint_clusters_list.tsv: + type: file + description: | + a TSV containing a list of all breakpoint clusters +- pattern: "${prefix}/all_SVs/breakpoints_clusters_list.tsv" ++ pattern: "${prefix}/all_SVs/breakpoint_clusters_list.tsv" + ontologies: [] + all_breakpoints_clusters: + - - meta: + type: map + description: | + Groovy Map containing sample information +- - ${prefix}/all_SVs/breakpoints_clusters.tsv: ++ - ${prefix}/all_SVs/breakpoint_clusters.tsv: + type: file + description: | + TSV file listing meta information in breakpoint clusters +- pattern: "${prefix}/all_SVs/breakpoints_clusters.tsv" ++ pattern: "${prefix}/all_SVs/breakpoint_clusters.tsv" + ontologies: [] + all_plots: + - - meta: +@@ -188,33 +209,33 @@ + type: map + description: | + Groovy Map containing sample information +- - ${prefix}/somatic_SVs/severus_somatic.vcf: ++ - ${prefix}/somatic_SVs/severus_somatic.vcf.gz: + type: file + description: | +- VCF file containing somatic structural variants (SV) +- pattern: "${prefix}/somatic_SVs/severus_all.vcf" ++ bgzipped VCF file containing somatic structural variants (SV) ++ pattern: "${prefix}/somatic_SVs/severus_somatic.vcf.gz" + ontologies: [] + somatic_breakpoints_clusters_list: + - - meta: + type: map + description: | + Groovy Map containing sample information +- - ${prefix}/somatic_SVs/breakpoints_clusters_list.tsv: ++ - ${prefix}/somatic_SVs/breakpoint_clusters_list.tsv: + type: file + description: | + TSV file containing full list of somatic breakpoint clusters +- pattern: "${prefix}/somatic_SVs/breakpoints_clusters_list.tsv" ++ pattern: "${prefix}/somatic_SVs/breakpoint_clusters_list.tsv" + ontologies: [] + somatic_breakpoints_clusters: + - - meta: + type: map + description: | + Groovy Map containing sample information +- - ${prefix}/somatic_SVs/breakpoints_clusters.tsv: ++ - ${prefix}/somatic_SVs/breakpoint_clusters.tsv: + type: file + description: | + TSV file containing meta information of somatic breakpoint clusters +- pattern: "${prefix}/somatic_SVs/breakpoints_clusters.tsv" ++ pattern: "${prefix}/somatic_SVs/breakpoint_clusters.tsv" + ontologies: [] + somatic_plots: + - - meta: + Changes in 'severus/main.nf': --- modules/nf-core/severus/main.nf +++ modules/nf-core/severus/main.nf -@@ -8,8 +8,8 @@ - 'community.wave.seqera.io/library/severus:1.7--d16d59609ef4ee7d' }" +@@ -3,13 +3,18 @@ + label 'process_medium' + + conda "${moduleDir}/environment.yml" ++ // Patched Severus 1.7 (github.com/AmberVerhasselt/Severus/tree/whitelist-reciprocal-corroboration, 6813dee) carries the --whitelist fixes; ++ // without --whitelist its VCF records are identical to stock 1.7 (the header adds a WL_RESCUE INFO line). Revert to the biocontainer once ++ // KolmogorovLab/Severus carries the fixes. ++ // Conda installs stock bioconda Severus, so --severus_whitelist is refused under conda at startup (utils_nfcore_lrsomatic_pipeline). + container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ? +- 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/8f/8fd0858ee067f8b95246e57683a7431bc126929b4203fbda8e315cd94d2570ad/data': +- 'community.wave.seqera.io/library/severus:1.7--d16d59609ef4ee7d' }" ++ 'oras://docker.io/amberverhasselt/severus-sif:1.7-whitelist-6813dee': ++ 'docker.io/amberverhasselt/severus:1.7-whitelist-6813dee' }" input: - tuple val(meta), path(target_input), path(target_index), path(control_input), path(control_index), path(vcf) - tuple val(meta2), path(bed) + tuple val(meta), path(target_input), path(target_index), path(control_input), path(control_index), path(vcf), path(tbi) + tuple val(meta2), path(bed), path(pon_path) ++ tuple val(meta3), path(whitelist) output: tuple val(meta), path("${prefix}/severus.log") , emit: log -@@ -19,13 +19,13 @@ +@@ -19,13 +24,13 @@ tuple val(meta), path("${prefix}/read_ids.csv") , emit: read_ids , optional: true tuple val(meta), path("${prefix}/severus_collaped_dup.bed") , emit: collapsed_dup , optional: true tuple val(meta), path("${prefix}/severus_LOH.bed") , emit: loh , optional: true @@ -35,11 +168,12 @@ Changes in 'severus/main.nf': tuple val(meta), path("${prefix}/somatic_SVs/plots/severus*.html") , emit: somatic_plots , optional: true tuple val("${task.process}"), val('severus'), eval("severus --version"), emit: versions_severus, topic: versions when: -@@ -38,15 +38,23 @@ +@@ -38,15 +43,25 @@ def control = control_input ? "--control-bam ${control_input}" : "" def vntr_bed = bed ? "--vntr-bed ${bed}" : "" def phasing_vcf = vcf ? "--phasing-vcf ${vcf}" : "" + def pon = pon_path && (!control_input) ? "--PON ${pon_path}" : "" ++ def whitelist_bed = whitelist ? "--whitelist ${whitelist}" : "" + """ severus \\ @@ -50,6 +184,7 @@ Changes in 'severus/main.nf': + $pon \\ $control \\ $phasing_vcf \\ ++ $whitelist_bed \\ --out-dir ${prefix} + + bgzip ${prefix}/somatic_SVs/severus_somatic.vcf @@ -61,6 +196,78 @@ Changes in 'severus/main.nf': stub: 'modules/nf-core/severus/tests/nextflow.config' is unchanged -'modules/nf-core/severus/tests/main.nf.test' is unchanged +Changes in 'severus/tests/main.nf.test': +--- modules/nf-core/severus/tests/main.nf.test ++++ modules/nf-core/severus/tests/main.nf.test +@@ -21,9 +21,11 @@ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam.bai', checkIfExists: true), + [], + [], ++ [], + [] +- ] +- input[1] = [[],[]] ++ ] ++ input[1] = [[],[],[]] ++ input[2] = [[:],[]] + """ + } + } +@@ -60,9 +62,11 @@ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam.bai', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), ++ [], + [] + ] +- input[1] = [[],[]] ++ input[1] = [[],[],[]] ++ input[2] = [[:],[]] + """ + } + } +@@ -103,8 +107,10 @@ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf', checkIfExists: true), ++ [] + ] +- input[1] = [[],[]] ++ input[1] = [[],[],[]] ++ input[2] = [[:],[]] + """ + } + } +@@ -145,11 +151,14 @@ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf', checkIfExists: true), ++ [] + ] + input[1] = [ + [ id:'bed'], // meta map +- file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.blacklist_intervals.bed', checkIfExists: true) ++ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.blacklist_intervals.bed', checkIfExists: true), ++ [] + ] ++ input[2] = [[:],[]] + """ + } + } +@@ -189,9 +198,11 @@ + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), + [], + [], ++ [], + [] +- ] +- input[1] = [[],[]] ++ ] ++ input[1] = [[],[],[]] ++ input[2] = [[:],[]] + """ + } + } + 'modules/nf-core/severus/tests/main.nf.test.snap' is unchanged ************************************************************ diff --git a/modules/nf-core/severus/tests/main.nf.test b/modules/nf-core/severus/tests/main.nf.test index a6ab42ed..43211dc4 100644 --- a/modules/nf-core/severus/tests/main.nf.test +++ b/modules/nf-core/severus/tests/main.nf.test @@ -21,9 +21,11 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam.bai', checkIfExists: true), [], [], + [], [] - ] - input[1] = [[],[]] + ] + input[1] = [[],[],[]] + input[2] = [[:],[]] """ } } @@ -60,9 +62,11 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam.bai', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), + [], [] ] - input[1] = [[],[]] + input[1] = [[],[],[]] + input[2] = [[:],[]] """ } } @@ -103,8 +107,10 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf', checkIfExists: true), + [] ] - input[1] = [[],[]] + input[1] = [[],[],[]] + input[2] = [[:],[]] """ } } @@ -145,11 +151,14 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gvcf/test.genome.vcf', checkIfExists: true), + [] ] input[1] = [ [ id:'bed'], // meta map - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.blacklist_intervals.bed', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.blacklist_intervals.bed', checkIfExists: true), + [] ] + input[2] = [[:],[]] """ } } @@ -189,9 +198,11 @@ nextflow_process { file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), [], [], + [], [] - ] - input[1] = [[],[]] + ] + input[1] = [[],[],[]] + input[2] = [[:],[]] """ } } diff --git a/nextflow.config b/nextflow.config index a5c0663a..7614abc6 100644 --- a/nextflow.config +++ b/nextflow.config @@ -111,6 +111,8 @@ params { // Severus options severus_minsupport = 3 + severus_whitelist = null // BED of regions where every SV is reported (Severus --whitelist) + severus_whitelist_args = null // Savana options savana_pb_minsupport = 10 diff --git a/nextflow_schema.json b/nextflow_schema.json index f596e8be..e3fd4a00 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -369,6 +369,21 @@ "severus_minsupport": { "type": "integer", "default": 3 + }, + "severus_whitelist": { + "type": "string", + "format": "file-path", + "exists": true, + "pattern": "^\\S+\\.bed$", + "description": "BED file of regions in which Severus reports every SV (Severus' --whitelist). Passed to Severus as --whitelist; its VCFs feed SV VEP, Wakhan and the report as usual. Not available under Conda.", + "help_text": "Inside the whitelisted regions the patched build skips the read-quality, minimum-support and VNTR filters, and keeps single-read junctions only when a reciprocal or independently supported junction corroborates them. Use it for loci such as the IG and TCR genes, where translocations are often carried by few, divergent reads.", + "fa_icon": "fas fa-file-alt" + }, + "severus_whitelist_args": { + "type": "string", + "description": "Extra arguments for the whitelist Severus run, e.g. `--whitelist-single-read any`, `--whitelist-allow-intra-region` or `--write-alignments`. Only used with `--severus_whitelist`.", + "help_text": "Appended after `--min-support --output-read-ids`, so a later flag wins where Severus allows it. Ignored unless `--severus_whitelist` is set. `--whitelist-single-read` takes `reciprocal` (default), `any` or `off`; `--write-alignments` additionally publishes a `read_alignments` file.", + "fa_icon": "fas fa-terminal" } } }, diff --git a/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf b/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf index d92ca2cc..f6370e46 100644 --- a/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_lrsomatic_pipeline/main.nf @@ -240,6 +240,16 @@ def validateInputParameters() { genomeExistsError() validateReportGenePanels() validateSvAnnotationParams() + validateSeverusWhitelist() +} + +// +// The --whitelist fixes exist only in the patched Severus image; bioconda's severus would run the unfixed whitelist logic +// +def validateSeverusWhitelist() { + if (params.severus_whitelist && workflow.profile.tokenize(',').intersect(['conda', 'mamba']).size() >= 1) { + error("--severus_whitelist: not supported under Conda/Mamba, which installs stock Severus without the whitelist fixes. Use Docker / Singularity / Apptainer, or run without --severus_whitelist.") + } } // diff --git a/tests/modules/severus_whitelist.nf.test b/tests/modules/severus_whitelist.nf.test new file mode 100644 index 00000000..b270b99c --- /dev/null +++ b/tests/modules/severus_whitelist.nf.test @@ -0,0 +1,92 @@ +nextflow_process { + + name "Test Process SEVERUS with and without --whitelist" + script "../../modules/nf-core/severus/main.nf" + process "SEVERUS" + + tag "modules" + tag "severus" + tag "small" + + // Lives here rather than in modules/nf-core/severus/tests, which nf-test.config ignores, so PR CI runs it; + // not directly in tests/, where nf-core lint (nf_test_content) treats every *.nf.test as a pipeline test. + // Paired, because without a control or PON Severus writes no somatic_SVs and the module's bgzip step fails. + // Real Severus on the nf-core nanopore test BAMs: checks that the patched image runs, that --whitelist reaches + // the command only when a whitelist is given, and that the bgzipped VCFs are emitted either way. + test("paired - no whitelist") { + + when { + process { + """ + input[0] = [ + [ id:'test', paired_data:true ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam.bai', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), + [], + [] + ] + input[1] = [ [:], [], [] ] + input[2] = [ [:], [] ] + """ + } + } + + then { + def cmd = file(process.out.log[0][1]).readLines().find { it.contains('Cmd:') } + assertAll( + { assert process.success }, + { assert !cmd.contains('--whitelist') }, + { assert file(process.out.log[0][1]).readLines().last().contains('Writing vcf') }, + { assert snapshot( + path(process.out.all_vcf[0][1]).linesGzip.findAll { !it.startsWith('#') }, + path(process.out.somatic_vcf[0][1]).linesGzip.findAll { !it.startsWith('#') }, + file(process.out.all_vcf[0][1]).name, + file(process.out.somatic_vcf[0][1]).name, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + } + + test("paired - whitelist") { + + when { + process { + """ + input[0] = [ + [ id:'test', paired_data:true ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test2.sorted.bam.bai', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.phased.bam.bai', checkIfExists: true), + [], + [] + ] + input[1] = [ [:], [], [] ] + input[2] = [ + [:], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.bed', checkIfExists: true) + ] + """ + } + } + + then { + def cmd = file(process.out.log[0][1]).readLines().find { it.contains('Cmd:') } + assertAll( + { assert process.success }, + { assert cmd.contains('--whitelist genome.bed') }, + { assert file(process.out.log[0][1]).readLines().last().contains('Writing vcf') }, + { assert snapshot( + path(process.out.all_vcf[0][1]).linesGzip.findAll { !it.startsWith('#') }, + path(process.out.somatic_vcf[0][1]).linesGzip.findAll { !it.startsWith('#') }, + file(process.out.all_vcf[0][1]).name, + file(process.out.somatic_vcf[0][1]).name, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } + ) + } + } +} diff --git a/tests/modules/severus_whitelist.nf.test.snap b/tests/modules/severus_whitelist.nf.test.snap new file mode 100644 index 00000000..0fa7f2a7 --- /dev/null +++ b/tests/modules/severus_whitelist.nf.test.snap @@ -0,0 +1,74 @@ +{ + "paired - whitelist": { + "content": [ + [ + "chr22\t10108\tseverus_BND0_1\tN\t]chr22:18016]N\t13.0\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=7908;MATE_ID=severus_BND0_2;BND_TYPE=DUP_LIKE;STRANDS=-+;MAPQ=13.0;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=10:5:3:14:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:38:0\t0/1:0.09:0.14,0.00,0.00:21:2", + "chr22\t10116\tseverus_BND1_1\tN\t]chr22:15265]N\t9.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=5149;MATE_ID=severus_BND1_2;BND_TYPE=DUP_LIKE;STRANDS=-+;MAPQ=9.5;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=10:5:3:2:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:38:0\t0/1:0.12:0.25,0.00,0.00:15:2", + "chr22\t10126\tseverus_BND2_1\tN\t[chr22:13460[N\t12.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=3334;MATE_ID=severus_BND2_2;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=12.5;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=10:5:3:29:6:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:38:0\t0/1:0.07:0.10,0.00,0.00:28:2", + "chr22\t13433\tseverus_INS10\tN\tTGGAAGATGCTGTGGTGAGTCAGTGAGTGTGAAGGCATAGGACCTTACTGTACACTACTGTAGACTTTATAAACACCATATGCTTAGGCTACACCAAAAATTTTT\t36.0\tPASS\tPRECISE;SVTYPE=INS;SVLEN=105;MAPQ=36.0;SUPP_READS=2:0:0:2:0:0;REF_READS=6:6:3:6:6:3;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:24:0\t0/1:0.13:0.33,0.00,0.00:13:2", + "chr22\t13460\tseverus_BND2_2\tN\t[chr22:10126[N\t12.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=3334;MATE_ID=severus_BND2_1;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=12.5;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=29:6:3:10:5:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:26:0\t0/1:0.07:0.10,0.00,0.00:28:2", + "chr22\t13466\tseverus_BND3_1\tN\t]chr22:14087]N\t12.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=621;MATE_ID=severus_BND3_2;BND_TYPE=DUP_LIKE;STRANDS=-+;MAPQ=12.5;PHASESETID=0|0;HP=0|0;SUPP_READS=3:0:0:3:0:0;REF_READS=29:6:3:17:6:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:26:0\t0/1:0.09:0.12,0.00,0.00:32:3", + "chr22\t13466\tseverus_BND4_1\tN\t]chr22:20713]N\t7.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=7247;MATE_ID=severus_BND4_2;BND_TYPE=DUP_LIKE;STRANDS=-+;MAPQ=7.5;PHASESETID=0|0;HP=0|0;SUPP_READS=3:0:0:3:0:0;REF_READS=29:6:3:4:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:26:0\t0/1:0.10:0.16,0.00,0.00:26:3", + "chr22\t14087\tseverus_BND3_2\tN\tN[chr22:13466[\t12.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=621;MATE_ID=severus_BND3_1;BND_TYPE=DUP_LIKE;STRANDS=+-;MAPQ=12.5;PHASESETID=0|0;HP=0|0;SUPP_READS=3:0:0:3:0:0;REF_READS=17:6:3:29:6:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:24:0\t0/1:0.09:0.12,0.00,0.00:32:3", + "chr22\t15265\tseverus_BND1_2\tN\tN[chr22:10116[\t9.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=5149;MATE_ID=severus_BND1_1;BND_TYPE=DUP_LIKE;STRANDS=+-;MAPQ=9.5;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=2:6:4:10:5:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:27:0\t0/1:0.12:0.25,0.00,0.00:15:2", + "chr22\t17458\tseverus_BND5_1\tN\t[chr22:23304[N\t15.0\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=5846;MATE_ID=severus_BND5_2;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=15.0;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=5:6:4:10:5:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:43:0\t0/1:0.11:0.22,0.00,0.00:17:2", + "chr22\t18016\tseverus_BND0_2\tN\tN[chr22:10108[\t13.0\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=7908;MATE_ID=severus_BND0_1;BND_TYPE=DUP_LIKE;STRANDS=+-;MAPQ=13.0;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=14:6:4:10:5:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:26:0\t0/1:0.09:0.14,0.00,0.00:21:2", + "chr22\t18120\tseverus_BND6_1\tN\t[chr22:23303[N\t24.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=BND;SVLEN=5183;MATE_ID=severus_BND6_2;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=24.0;PHASESETID=0|0;HP=0|0;SUPP_READS=3:0:0:3:0:0;REF_READS=23:6:4:10:5:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:73:0\t0/1:0.10:0.16,0.00,0.00:26:3", + "chr22\t18187\tseverus_BND7_1\tN\t[chr22:20411[N\t22.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=BND;SVLEN=2224;MATE_ID=severus_BND7_2;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=22.0;PHASESETID=0|0;HP=0|0;SUPP_READS=5:0:0:5:0:0;REF_READS=23:6:4:5:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:73:0\t0/1:0.17:0.26,0.00,0.00:24:5", + "chr22\t18260\tseverus_INS11\tN\tACTGCACCCCAGCCTGGTCAACAGGGCGAGACTGCATCTCAGAAAAAAAAAAAAAA\t15.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=INS;SVLEN=57;MAPQ=15.0;PHASESETID=0|0;HP=0|0;SUPP_READS=7:0:0:7:0:0;REF_READS=30:6:4:30:6:4;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:51:0\t0/1:0.17:0.23,0.00,0.00:33:7", + "chr22\t20411\tseverus_BND7_2\tN\t[chr22:18187[N\t22.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=BND;SVLEN=2224;MATE_ID=severus_BND7_1;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=22.0;PHASESETID=0|0;HP=0|0;SUPP_READS=5:0:0:5:0:0;REF_READS=5:6:4:23:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:27:0\t0/1:0.17:0.26,0.00,0.00:24:5", + "chr22\t20713\tseverus_BND4_2\tN\tN[chr22:13466[\t7.5\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=7247;MATE_ID=severus_BND4_1;BND_TYPE=DUP_LIKE;STRANDS=+-;MAPQ=7.5;PHASESETID=0|0;HP=0|0;SUPP_READS=3:0:0:3:0:0;REF_READS=4:6:4:29:6:3;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:26:0\t0/1:0.10:0.16,0.00,0.00:26:3", + "chr22\t23303\tseverus_BND6_2\tN\t[chr22:18120[N\t24.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=BND;SVLEN=5183;MATE_ID=severus_BND6_1;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=24.0;PHASESETID=0|0;HP=0|0;SUPP_READS=3:0:0:3:0:0;REF_READS=10:5:4:23:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:28:0\t0/1:0.10:0.16,0.00,0.00:26:3", + "chr22\t23304\tseverus_BND5_2\tN\t[chr22:17458[N\t15.0\tFAIL_MAP_CONS\tPRECISE;SVTYPE=BND;SVLEN=5846;MATE_ID=severus_BND5_1;BND_TYPE=INV_LIKE;STRANDS=--;MAPQ=15.0;PHASESETID=0|0;HP=0|0;SUPP_READS=2:0:0:2:0:0;REF_READS=10:5:4:5:6:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:28:0\t0/1:0.11:0.22,0.00,0.00:17:2", + "chr22\t23312\tseverus_DUP8\tN\t\t43.5\tPASS\tPRECISE;SVTYPE=DUP;SVLEN=5374;END=28686;STRANDS=-+;DETAILED_TYPE=tandem_duplication;MAPQ=43.5;SUPP_READS=2:0:0:2:0:0;REF_READS=10:5:4:7:5:4;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:28:0\t0/1:0.11:0.20,0.00,0.00:17:2", + "chr22\t27693\tseverus_BND9_1\tN\tN[chr22:28338[\t24.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=BND;SVLEN=645;MATE_ID=severus_BND9_2;BND_TYPE=DEL_LIKE;STRANDS=+-;MAPQ=24.0;PHASESETID=0|0;HP=0|0;SUPP_READS=4:0:0:4:0:0;REF_READS=8:5:4:13:5:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:34:0\t0/1:0.17:0.29,0.00,0.00:19:4", + "chr22\t28338\tseverus_BND9_2\tN\t]chr22:27693]N\t24.0\tFAIL_MAP_CONS\tIMPRECISE;SVTYPE=BND;SVLEN=645;MATE_ID=severus_BND9_1;BND_TYPE=DEL_LIKE;STRANDS=-+;MAPQ=24.0;PHASESETID=0|0;HP=0|0;SUPP_READS=4:0:0:4:0:0;REF_READS=13:5:4:8:5:4;CLUSTERID=severus_0;INSIDE_WHITELIST=TRUE;WL_RESCUE=WHITELIST\tGT:VAF:hVAF:DR:DV\t./.:0:0,0,0:31:0\t0/1:0.17:0.29,0.00,0.00:19:4" + ], + [ + + ], + "severus_all.vcf.gz", + "severus_somatic.vcf.gz", + { + "versions_severus": [ + [ + "SEVERUS", + "severus", + "1.7" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-10-02T21:55:20.932321899" + }, + "paired - no whitelist": { + "content": [ + [ + + ], + [ + + ], + "severus_all.vcf.gz", + "severus_somatic.vcf.gz", + { + "versions_severus": [ + [ + "SEVERUS", + "severus", + "1.7" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-10-02T21:55:13.3288247" + } +} \ No newline at end of file diff --git a/workflows/lrsomatic.nf b/workflows/lrsomatic.nf index 18d1fb5b..d7955da7 100644 --- a/workflows/lrsomatic.nf +++ b/workflows/lrsomatic.nf @@ -987,15 +987,17 @@ workflow LRSOMATIC { // normal_bam/bai are empty lists [] for tumor-only samples // - // MODULE: SEVERUS (label: process_high) + // MODULE: SEVERUS (label: process_medium) // Input: severus_input -- [meta, tumor_bam, tumor_bai, normal_bam, normal_bai, vcf, tbi] // [[:], bed_file, pon_file] -- optional target BED and panel-of-normals for SV filtering - // Output: .all_vcf -- [meta, vcf] -- all somatic SVs (sniffles2 format) + // [[:], whitelist] -- optional (--severus_whitelist): regions in which every SV is reported + // Output: .all_vcf / .somatic_vcf -- [meta, vcf.gz] -- all and somatic SVs // SEVERUS ( severus_input, - [[:], params.bed_file, params.pon_file] + [[:], params.bed_file, params.pon_file], + [[:], params.severus_whitelist ? file(params.severus_whitelist, checkIfExists: true) : []] ) SEVERUS.out.all_vcf