From 1c036be5f3ef139181e281537868352cb4318fed Mon Sep 17 00:00:00 2001 From: Arthur Gymer <24782660+awgymer@users.noreply.github.com> Date: Fri, 30 Oct 2026 14:33:28 +1030 Subject: [PATCH] feat(sniffles): add optional regions input Add an optional regions BED file to the input tuple. The module gives the file to Sniffles with --regions. Add a test that shows that the module calls only the SVs in the regions. --- modules/nf-core/sniffles/main.nf | 4 +- modules/nf-core/sniffles/meta.yml | 6 + modules/nf-core/sniffles/tests/main.nf.test | 50 ++- .../nf-core/sniffles/tests/main.nf.test.snap | 361 ++++++++++-------- 4 files changed, 248 insertions(+), 173 deletions(-) diff --git a/modules/nf-core/sniffles/main.nf b/modules/nf-core/sniffles/main.nf index 9df9a438fc96..fbc7187ad705 100644 --- a/modules/nf-core/sniffles/main.nf +++ b/modules/nf-core/sniffles/main.nf @@ -11,7 +11,7 @@ process SNIFFLES { : 'community.wave.seqera.io/library/htslib_sniffles:14a95caca8d8452b' }" input: - tuple val(meta), path(input), path(index), path(genotype_vcf) + tuple val(meta), path(input), path(index), path(genotype_vcf), path(regions) tuple val(meta2), path(fasta) tuple val(meta3), path(tandem_file) val(vcf_output) @@ -32,6 +32,7 @@ process SNIFFLES { def prefix = task.ext.prefix ?: "${meta.id}" def reference = fasta ? "--reference ${fasta}" : "" def tandem_repeats = tandem_file ? "--tandem-repeats ${tandem_file}" : '' + def regions_bed = regions ? "--regions ${regions}" : '' def vcf = vcf_output ? "--vcf ${prefix}.vcf.gz": '' def snf = snf_output ? "--snf ${prefix}.snf": '' // Sniffles reads the sites file as plain text, so a compressed one is decompressed first (fritzsedlazeck/Sniffles#613) @@ -45,6 +46,7 @@ process SNIFFLES { $reference \\ -t $task.cpus \\ $tandem_repeats \\ + $regions_bed \\ $genotype \\ $vcf \\ $snf \\ diff --git a/modules/nf-core/sniffles/meta.yml b/modules/nf-core/sniffles/meta.yml index 00bdb8bc287d..467c8b565166 100644 --- a/modules/nf-core/sniffles/meta.yml +++ b/modules/nf-core/sniffles/meta.yml @@ -36,6 +36,12 @@ input: pattern: "*.{vcf,vcf.gz}" ontologies: - edam: http://edamontology.org/format_3016 + - regions: + type: file + description: Optional BED file of regions to process. Sniffles only processes reads in these regions. Use an empty list (`[]`) to process all regions. + pattern: "*.bed" + ontologies: + - edam: http://edamontology.org/format_3003 - - meta2: type: map description: | diff --git a/modules/nf-core/sniffles/tests/main.nf.test b/modules/nf-core/sniffles/tests/main.nf.test index cb6d1dc601ca..5fb3a01a408a 100644 --- a/modules/nf-core/sniffles/tests/main.nf.test +++ b/modules/nf-core/sniffles/tests/main.nf.test @@ -19,6 +19,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -55,6 +56,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -89,6 +91,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -126,6 +129,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -168,6 +172,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -201,6 +206,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -234,6 +240,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -267,6 +274,7 @@ nextflow_process { [ id:'test' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/test.sorted.bam.bai', checkIfExists: true), + [], [] ] input[1] = [ @@ -301,7 +309,8 @@ nextflow_process { [ id:'hg002' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam.bai', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_sites.vcf.gz', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_sites.vcf.gz', checkIfExists: true), + [] ] input[1] = [[], []] input[2] = [[], []] @@ -347,7 +356,7 @@ nextflow_process { [ id:'hg002' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam.bai', checkIfExists: true) - ]).combine(GUNZIP.out.gunzip.map { _meta, vcf -> vcf }) + ]).combine(GUNZIP.out.gunzip.map { _meta, vcf -> [vcf, []] }) input[1] = [[], []] input[2] = [[], []] input[3] = true @@ -380,7 +389,8 @@ nextflow_process { [ id:'hg002' ], file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam', checkIfExists: true), file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam.bai', checkIfExists: true), - file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_sites.vcf.gz', checkIfExists: true) + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_sites.vcf.gz', checkIfExists: true), + [] ] input[1] = [[], []] input[2] = [[], []] @@ -399,4 +409,38 @@ nextflow_process { } + test("homo_sapiens - nanopore [bam, bai, [], bed], [], [], true, false - regions") { + + when { + process { + """ + input[0] = channel.of([ + [ id:'hg002' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/nanopore/bam/HG002_ont_sv_genotype/HG002_ont_sv_genotype.bam.bai', checkIfExists: true), + [] + ]).combine(channel.of("chr2\t71600000\t71700000").collectFile(name: 'regions.bed', newLine: true)) + input[1] = [[], []] + input[2] = [[], []] + input[3] = true + input[4] = false + """ + } + } + + then { + def records = path(process.out.vcf.get(0).get(1)).linesGzip.findAll { line -> !line.startsWith("#") } + assertAll( + { assert process.success }, + { assert records.every { line -> line.startsWith("chr2\t") } }, + { assert snapshot( + process.out.findAll { key, val -> key.startsWith("versions") }, + file(process.out.tbi.get(0).get(1)).name, + records, + ).match() } + ) + } + + } + } diff --git a/modules/nf-core/sniffles/tests/main.nf.test.snap b/modules/nf-core/sniffles/tests/main.nf.test.snap index e11c10fed216..b1380911c8d6 100644 --- a/modules/nf-core/sniffles/tests/main.nf.test.snap +++ b/modules/nf-core/sniffles/tests/main.nf.test.snap @@ -1,4 +1,196 @@ { + "homo_sapiens - nanopore [bam, bai, [], bed], [], [], true, false - regions": { + "content": [ + { + "versions_sniffles": [ + [ + "SNIFFLES", + "sniffles", + "2.8.1" + ] + ] + }, + "hg002.vcf.gz.tbi", + [ + "chr2\t71662936\tSniffles2.INS.0S0\tN\tTGTGTGTGTGTGTGCATATTTGTGTGTGTATGTCTGTGTCCATGTGTCTGCATATGTGTGTGGTGTGTGTATATTTGTGTATGTTTACGTGTGTG\t60\tPASS\tPRECISE;SVTYPE=INS;SVLEN=95;END=71662936;SUPPORT=1;COVERAGE=1,1,1,1,1;STRAND=+;PHASE=0,NULL,1,1,PASS,FAIL;STDEV_LEN=0;STDEV_POS=0;SUPPORT_LONG=0;SUPPORT_UNSCALED=1;VAF=1.000\tGT:GQ:DR:DV:PS\t1/1:2:0:1:.", + "chr2\t71691502\tSniffles2.DEL.1S0\tN\t\t60\tPASS\tPRECISE;SVTYPE=DEL;SVLEN=-92;END=71691594;SUPPORT=8;COVERAGE=16,16,16,16,16;STRAND=+-;PHASE=0,NULL,8,8,PASS,FAIL;STDEV_LEN=0.957;STDEV_POS=12.767;SUPPORT_SA=0;VAF=0.500\tGT:GQ:DR:DV:PS\t0/1:57:8:8:." + ] + ], + "timestamp": "2026-10-30T14:25:32.800944989", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.10.2" + } + }, + "homo_sapiens - [bam, bai], fasta, [], true, false": { + "content": [ + { + "versions_sniffles": [ + [ + "SNIFFLES", + "sniffles", + "2.8.1" + ] + ] + }, + "test.vcf.gz.tbi", + [ + "##fileformat=VCFv4.2", + "##source=Sniffles2_2.8.1" + ], + [ + "##ALT=", + "##ALT=", + "##ALT=", + "##ALT=", + "##ALT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=" + ] + ], + "timestamp": "2026-10-06T10:06:05.589273883", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, + "homo_sapiens - [bam, bai], fasta, bed, true, true": { + "content": [ + { + "versions_sniffles": [ + [ + "SNIFFLES", + "sniffles", + "2.8.1" + ] + ] + }, + "test.snf", + "test.vcf.gz.tbi", + [ + "##fileformat=VCFv4.2", + "##source=Sniffles2_2.8.1" + ], + [ + "##ALT=", + "##ALT=", + "##ALT=", + "##ALT=", + "##ALT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FORMAT=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##FILTER=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=", + "##INFO=" + ] + ], + "timestamp": "2026-10-06T10:06:21.576995175", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.6" + } + }, "homo_sapiens - [bam, bai], fasta, bed, true, true -stub": { "content": [ { @@ -343,90 +535,6 @@ "nextflow": "26.04.6" } }, - "homo_sapiens - [bam, bai], fasta, [], true, false": { - "content": [ - { - "versions_sniffles": [ - [ - "SNIFFLES", - "sniffles", - "2.8.1" - ] - ] - }, - "test.vcf.gz.tbi", - [ - "##fileformat=VCFv4.2", - "##source=Sniffles2_2.8.1" - ], - [ - "##ALT=", - "##ALT=", - "##ALT=", - "##ALT=", - "##ALT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=" - ] - ], - "timestamp": "2026-10-06T10:06:05.589273883", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - }, "homo_sapiens - [bam, bai], fasta, [], false, true -stub": { "content": [ { @@ -459,91 +567,6 @@ "nextflow": "26.04.6" } }, - "homo_sapiens - [bam, bai], fasta, bed, true, true": { - "content": [ - { - "versions_sniffles": [ - [ - "SNIFFLES", - "sniffles", - "2.8.1" - ] - ] - }, - "test.snf", - "test.vcf.gz.tbi", - [ - "##fileformat=VCFv4.2", - "##source=Sniffles2_2.8.1" - ], - [ - "##ALT=", - "##ALT=", - "##ALT=", - "##ALT=", - "##ALT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FORMAT=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##FILTER=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=", - "##INFO=" - ] - ], - "timestamp": "2026-10-06T10:06:21.576995175", - "meta": { - "nf-test": "0.9.5", - "nextflow": "26.04.6" - } - }, "homo_sapiens - [bam, bai], fasta, [], true, false -stub": { "content": [ {