diff --git a/modules/nf-core/varnet/main.nf b/modules/nf-core/varnet/main.nf new file mode 100644 index 000000000000..f89d8810dd30 --- /dev/null +++ b/modules/nf-core/varnet/main.nf @@ -0,0 +1,59 @@ +process VARNET { + tag "$meta.id" + label 'process_high_memory' + + container "docker.io/kiranchari/varnet:latest" + + input: + tuple val(meta), path(input_tumor), path(index_tumor), path(input_normal), path(index_normal) + tuple val(meta2), path(intervals) + tuple val(meta3), path(fasta) + tuple val(meta4), path(fai) + + output: + tuple val(meta), path("${prefix}/${prefix}.vcf.gz"), emit: vcf + tuple val("${task.process}"), val("varnet"), env("VARNET_VERSION"), emit: versions_varnet, topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + def regions = intervals ? "--region_bed \$WORKDIR/${intervals}" : "" + def normal = input_normal ? "--normal_bam \$WORKDIR/${input_normal}" : "" + """ + + WORKDIR=\$(pwd) + + cd /VarNet + export VARNET_VERSION=\$(python -c "from snvs.constants import __VERSION__; print(__VERSION__)") + TF_CPP_MIN_LOG_LEVEL=3 python /VarNet/filter.py \\ + --sample_name ${prefix} \\ + ${normal} \\ + --tumor_bam \$WORKDIR/${input_tumor} \\ + --reference \$WORKDIR/${fasta} \\ + --output_dir \$WORKDIR \\ + --processes ${task.cpus} \\ + ${regions} \\ + ${args} + + TF_CPP_MIN_LOG_LEVEL=3 python /VarNet/predict.py \\ + --sample_name ${prefix} \\ + ${normal} \\ + --tumor_bam \$WORKDIR/${input_tumor} \\ + --reference \$WORKDIR/${fasta} \\ + --output_dir \$WORKDIR \\ + --processes ${task.cpus} \\ + ${args} + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + """ + export VARNET_VERSION=\$(python -c "from snvs.constants import __VERSION__; print(__VERSION__)") + mkdir -p ${prefix} + echo "" | gzip > ${prefix}/${prefix}.vcf.gz + """ +} + diff --git a/modules/nf-core/varnet/meta.yml b/modules/nf-core/varnet/meta.yml new file mode 100644 index 000000000000..922c693a3763 --- /dev/null +++ b/modules/nf-core/varnet/meta.yml @@ -0,0 +1,112 @@ +name: "varnet" +description: VarNet is a deep learning-based somatic variant caller that utilizes + a two-stage filtering and prediction architecture. It processes aligned reads from + tumor and normal data to identify somatic mutations using a deep neural network + approach. +keywords: + - variant calling + - machine learning + - neural network + - somatic +tools: + - "varnet": + description: "A deep learning-based somatic variant caller" + homepage: "https://github.com/skandlab/VarNet" + documentation: "https://github.com/skandlab/VarNet" + tool_dev_url: "https://github.com/skandlab/VarNet" + doi: "10.1038/s41467-022-31765-8" + licence: + - "PolyForm Noncommercial License 1.0.0" + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - input_normal: + type: file + description: BAM/CRAM file from normal sample + pattern: "*.{bam,cram}" + ontologies: [] + - index_normal: + type: file + description: Index of normal BAM/CRAM file + pattern: "*.{bai,crai}" + ontologies: [] + - input_tumor: + type: file + description: BAM/CRAM file from tumor sample + pattern: "*.{bam,cram}" + ontologies: [] + - index_tumor: + type: file + description: Index of tumor BAM/CRAM file + pattern: "*.{bai,crai}" + ontologies: [] + - - meta2: + type: map + description: | + Groovy Map containing reference information + - intervals: + type: file + description: BED file containing target intervals + pattern: "*.bed" + ontologies: [] + - - meta3: + type: map + description: | + Groovy Map containing reference information + - fasta: + type: file + description: The reference fasta file + pattern: "*.{fasta,fa}" + ontologies: [] + - - meta4: + type: map + description: | + Groovy Map containing reference information + - fai: + type: file + description: Index of reference fasta file + pattern: "*.fai" + ontologies: [] +output: + vcf: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - ${prefix}.vcf.gz: + type: file + description: Compressed VCF file + pattern: "*.vcf.gz" + ontologies: + - edam: http://edamontology.org/format_3989 # GZIP format + + versions_varnet: + - - ${task.process}: + type: string + description: The name of the process + - varnet: + type: string + description: The name of the tool + - "1.5.0": + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - varnet: + type: string + description: The name of the tool + - "1.5.0": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@kiranchari" +maintainers: + - "@kiranchari" diff --git a/modules/nf-core/varnet/tests/main.nf.test b/modules/nf-core/varnet/tests/main.nf.test new file mode 100644 index 000000000000..5d0589cb2588 --- /dev/null +++ b/modules/nf-core/varnet/tests/main.nf.test @@ -0,0 +1,95 @@ +nextflow_process { + + name "Test Process VARNET" + script "../main.nf" + process "VARNET" + + tag "modules" + tag "modules_nfcore" + tag "varnet" + config './nextflow.config' + + test("tumor_normal_pair") { + + when { + process { + """ + input[0] = [ + [ id:'test' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true) + ] + input[1] = [ + [ id:'test_region' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/multi_intervals.bed', checkIfExists: true) + ] + input[2] = [ + [ id:'genome' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true) + ] + input[3] = [ + [ id:'genome' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { + assert snapshot( + process.out.vcf.collect { file(it[1]).getName() }, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() + } + ) + } + + } + +test("tumor_only") { + + when { + process { + """ + input[0] = [ + [ id:'test_tumor_only' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/test2.paired_end.recalibrated.sorted.bam.bai', checkIfExists: true), + [], // input_normal is empty + [] // index_normal is empty + ] + input[1] = [ + [ id:'intervals' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/multi_intervals.bed', checkIfExists: true) + ] + input[2] = [ + [ id:'genome' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true) + ] + input[3] = [ + [ id:'genome' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta.fai', checkIfExists: true) + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { + assert snapshot( + process.out.vcf.collect { file(it[1]).getName() }, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() + } + ) + } + } +} + diff --git a/modules/nf-core/varnet/tests/main.nf.test.snap b/modules/nf-core/varnet/tests/main.nf.test.snap new file mode 100644 index 000000000000..4cce20042478 --- /dev/null +++ b/modules/nf-core/varnet/tests/main.nf.test.snap @@ -0,0 +1,44 @@ +{ + "tumor_only": { + "content": [ + [ + "test_tumor_only_out.vcf.gz" + ], + { + "versions_varnet": [ + [ + "VARNET", + "varnet", + "1.5.2" + ] + ] + } + ], + "timestamp": "2026-06-04T14:01:04.66446019", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.3" + } + }, + "tumor_normal_pair": { + "content": [ + [ + "test_out.vcf.gz" + ], + { + "versions_varnet": [ + [ + "VARNET", + "varnet", + "1.5.2" + ] + ] + } + ], + "timestamp": "2026-06-04T13:53:19.433330376", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.3" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/varnet/tests/nextflow.config b/modules/nf-core/varnet/tests/nextflow.config new file mode 100644 index 000000000000..249b54ffa6a8 --- /dev/null +++ b/modules/nf-core/varnet/tests/nextflow.config @@ -0,0 +1,9 @@ +process { + withName: VARNET { + ext.prefix = { "${meta.id}_out" } + memory = '16GB' + cpus = 1 + // ext.args is no longer needed for the region since it's handled via the input channel + + } +}