From 94a4ce23a06e024187756ce1b840c59b09f01eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=BCbra=20Narc=C4=B1?= Date: Thu, 9 Jul 2026 15:57:46 +0200 Subject: [PATCH 1/3] add aardvark merge --- .../nf-core/aardvark/merge/environment.yml | 7 + modules/nf-core/aardvark/merge/main.nf | 66 ++++++ modules/nf-core/aardvark/merge/meta.yml | 160 +++++++++++++ .../nf-core/aardvark/merge/tests/main.nf.test | 98 ++++++++ .../aardvark/merge/tests/main.nf.test.snap | 217 ++++++++++++++++++ .../aardvark/merge/tests/nextflow.config | 6 + 6 files changed, 554 insertions(+) create mode 100644 modules/nf-core/aardvark/merge/environment.yml create mode 100644 modules/nf-core/aardvark/merge/main.nf create mode 100644 modules/nf-core/aardvark/merge/meta.yml create mode 100644 modules/nf-core/aardvark/merge/tests/main.nf.test create mode 100644 modules/nf-core/aardvark/merge/tests/main.nf.test.snap create mode 100644 modules/nf-core/aardvark/merge/tests/nextflow.config diff --git a/modules/nf-core/aardvark/merge/environment.yml b/modules/nf-core/aardvark/merge/environment.yml new file mode 100644 index 000000000000..060ca934960d --- /dev/null +++ b/modules/nf-core/aardvark/merge/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::aardvark=0.10.5 diff --git a/modules/nf-core/aardvark/merge/main.nf b/modules/nf-core/aardvark/merge/main.nf new file mode 100644 index 000000000000..cd923c286b62 --- /dev/null +++ b/modules/nf-core/aardvark/merge/main.nf @@ -0,0 +1,66 @@ +process AARDVARK_MERGE { + tag "$meta.id" + label 'process_low' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/aardvark:0.10.5--h4349ce8_0': + 'quay.io/biocontainers/aardvark:0.10.5--h4349ce8_0' }" + + input: + tuple val(meta), path(vcfs), path(indexes) + tuple val(meta2), path(fasta) + tuple val(meta3), path(bed) + + output: + tuple val(meta), path('*.summary.tsv') , emit: summary + tuple val(meta), path('*.passing.vcf.gz') , emit: passing_vcf + tuple val(meta), path('*.passing.vcf.gz.tbi') , emit: passing_vcf_index + tuple val(meta), path('*.regions.bed.gz') , emit: passing_regions + tuple val(meta), path('*.regions.bed.gz.tbi') , emit: passing_regions_index + tuple val(meta), path('*.failed_regions.bed.gz') , emit: failed_regions + tuple val(meta), path('*.failed_regions.bed.gz.tbi') , emit: failed_regions_index + tuple val(meta), path('*.json') , emit: runinfo + tuple val("${task.process}"), val('aardvark'), eval("aardvark merge --version 2>&1 | sed 's/aardvark-bio-merge //; s/-conda//'"), topic: versions, emit: versions_aardvark + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def inputs = [vcfs].flatten().collect { "--input-vcf ${it}" }.join(' ') + + """ + aardvark merge \\ + --threads $task.cpus \\ + --reference $fasta \\ + $inputs \\ + --regions ${bed} \\ + --output-vcfs $prefix \\ + --output-debug $prefix \\ + --output-summary ${prefix}.summary.tsv \\ + $args + + for f in ${prefix}/*; do + mv "\$f" "${prefix}.\${f##*/}" + done + + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + echo $args + + echo "" | gzip > ${prefix}.passing.vcf.gz + echo "" | gzip > ${prefix}.regions.bed.gz + echo "" | gzip > ${prefix}.failed_regions.bed.gz + touch ${prefix}.passing.vcf.gz.tbi + touch ${prefix}.regions.bed.gz.tbi + touch ${prefix}.failed_regions.bed.gz.tbi + touch ${prefix}.summary.tsv + touch ${prefix}.cli_settings.json + """ +} diff --git a/modules/nf-core/aardvark/merge/meta.yml b/modules/nf-core/aardvark/merge/meta.yml new file mode 100644 index 000000000000..92e4dda793a1 --- /dev/null +++ b/modules/nf-core/aardvark/merge/meta.yml @@ -0,0 +1,160 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: "aardvark_merge" +description: A tool to evaluate and merge multiple variant calls into a consensus VCF. +keywords: + - variant calling + - vcf + - comparison + - consensus + - merging +tools: + - aardvark: + description: | + The aardvark merge command provides a method to merge variant calls. This functionality is helpful when multiple + variant callers or technologies are used for the same sample. Merging variant sets can be complex and Aardvark + simplifies this process by modeling the variants as haplotypes. This allows for different merge strategies for + resolving conflicting variant sets. + homepage: "https://github.com/PacificBiosciences/aardvark" + documentation: "https://github.com/PacificBiosciences/aardvark/blob/main/docs/methods.md#merge-strategies" + tool_dev_url: "https://github.com/PacificBiosciences/aardvark" + doi: "10.1101/2025.10.03.680257" + licence: ["MIT"] + identifier: biotools:aardvark + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - vcfs: + type: file + description: List of VCF files to be merged + pattern: "*.{vcf.gz}" + ontologies: + - edam: "http://edamontology.org/format_3016" + - indexes: + type: file + description: List of index files for the input VCF files + pattern: "*.{vcf.gz.tbi,vcf.gz.csi,tbi,csi}" + - - meta2: + type: map + description: Groovy Map containing reference fasta information + - fasta: + type: file + description: Reference genome fasta file + pattern: "*.{fasta,fa,fasta.gz,fa.gz}" + ontologies: + - edam: http://edamontology.org/format_1929 # FASTA + - - meta3: + type: map + description: Groovy Map containing bed information + - bed: + type: file + description: Optional BED file containing genomic regions to restrict the merge operation + pattern: "*.{bed}" + ontologies: + - edam: "http://edamontology.org/format_3586" + +output: + summary: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.summary.tsv": + type: file + description: Global summary statistics of the variant merge + pattern: "*.summary.tsv" + ontologies: + - edam: "http://edamontology.org/format_3475" # TSV + passing_vcf: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.passing.vcf.gz": + type: file + description: Merged VCF file containing passing variants + pattern: "*.passing.vcf.gz" + ontologies: + - edam: "http://edamontology.org/format_3016" + passing_vcf_index: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.passing.vcf.gz.tbi": + type: file + description: Index file for the merged passing VCF + pattern: "*.passing.vcf.gz.tbi" + passing_regions: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.regions.bed.gz": + type: file + description: BED file of regions containing passing variants + pattern: "*.regions.bed.gz" + ontologies: + - edam: "http://edamontology.org/format_3586" + passing_regions_index: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.regions.bed.gz.tbi": + type: file + description: Index file for the passing regions BED + pattern: "*.regions.bed.gz.tbi" + failed_regions: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.failed_regions.bed.gz": + type: file + description: BED file of regions that failed merging criteria + pattern: "*.failed_regions.bed.gz" + ontologies: + - edam: "http://edamontology.org/format_3586" + failed_regions_index: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.failed_regions.bed.gz.tbi": + type: file + description: Index file for the failed regions BED + pattern: "*.failed_regions.bed.gz.tbi" + runinfo: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.json": + type: file + description: JSON file containing parameter settings used during the run + pattern: "*.json" + ontologies: + - edam: http://edamontology.org/format_3464 # JSON + versions_aardvark: + - - "${task.process}": + type: string + description: The name of the process + - "aardvark": + type: string + description: The name of the tool + - "aardvark merge --version 2>&1 | sed 's/aardvark-bio-merge //; s/-conda//'": + type: eval + description: The expression to obtain the version of the tool + +topics: + versions: + - - "${task.process}": + type: string + description: The name of the process + - "aardvark": + type: string + description: The name of the tool + - "aardvark merge --version 2>&1 | sed 's/aardvark-bio-merge //; s/-conda//'": + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@kubranarci" +maintainers: + - "@kubranarci" \ No newline at end of file diff --git a/modules/nf-core/aardvark/merge/tests/main.nf.test b/modules/nf-core/aardvark/merge/tests/main.nf.test new file mode 100644 index 000000000000..ad3702a2c632 --- /dev/null +++ b/modules/nf-core/aardvark/merge/tests/main.nf.test @@ -0,0 +1,98 @@ +nextflow_process { + + name "Test Process AARDVARK_MERGE" + script "../main.nf" + process "AARDVARK_MERGE" + + tag "modules" + tag "modules_nfcore" + tag "aardvark" + tag "aardvark/merge" + + config "./nextflow.config" + + test("homo_sapiens - vcf.gz") { + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/haplotypecaller_calls/test2_haplotc.vcf.gz', checkIfExists: true) + ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.tbi', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/haplotypecaller_calls/test2_haplotc.vcf.gz.tbi', checkIfExists: true) + ] + ] + input[1] = [ + [ id:'fasta' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true) + ] + input[2] = [ + [id:'bed' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/multi_intervals.bed', checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + path(process.out.passing_vcf[0][1]).vcf.summary, + file(process.out.passing_vcf[0][1]).name, + file(process.out.passing_vcf_index[0][1]).name, + file(process.out.failed_regions[0][1]).name, + process.out.passing_regions, + process.out.passing_regions_index, + process.out.failed_regions_index, + process.out.runinfo, + process.out.summary, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() + } + ) + } + + } + + test("homo_sapiens - vcf.gz - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test' ], // meta map + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/haplotypecaller_calls/test2_haplotc.vcf.gz', checkIfExists: true) + ], + [ file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/paired_mutect2_calls/test_test2_paired_mutect2_calls.vcf.gz.tbi', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/gatk/haplotypecaller_calls/test2_haplotc.vcf.gz.tbi', checkIfExists: true) + ] + ] + input[1] = [ + [ id:'fasta' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/genome.fasta', checkIfExists: true) + ] + input[2] = [ + [id:'bed' ], // meta map + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/chr21/sequence/multi_intervals.bed', checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot(process.out).match() } + ) + } + + } + +} diff --git a/modules/nf-core/aardvark/merge/tests/main.nf.test.snap b/modules/nf-core/aardvark/merge/tests/main.nf.test.snap new file mode 100644 index 000000000000..43d232db8999 --- /dev/null +++ b/modules/nf-core/aardvark/merge/tests/main.nf.test.snap @@ -0,0 +1,217 @@ +{ + "homo_sapiens - vcf.gz": { + "content": [ + "VcfFile [chromosomes=[chr21], sampleCount=1, variantCount=737, phased=false, phasedAutodetect=false]", + "test.passing.vcf.gz", + "test.passing.vcf.gz.tbi", + "test.failed_regions.bed.gz", + [ + [ + { + "id": "test" + }, + "test.regions.bed.gz:md5,307f7b70e725e34fc72cf0dce1ce02e6" + ] + ], + [ + [ + { + "id": "test" + }, + "test.regions.bed.gz.tbi:md5,65044f52414fd2ec57a700af9a00ff21" + ] + ], + [ + [ + { + "id": "test" + }, + "test.failed_regions.bed.gz.tbi:md5,ba7bcfa58c213e684162cbe00f884123" + ] + ], + [ + [ + { + "id": "test" + }, + "test.cli_settings.json:md5,15bc382f7d1503e71b50cd1bc742e49f" + ] + ], + [ + [ + { + "id": "test" + }, + "test.summary.tsv:md5,1092f71327ac5c46ecb746642328a6a3" + ] + ], + { + "versions_aardvark": [ + [ + "AARDVARK_MERGE", + "aardvark", + "0.10.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.5" + }, + "timestamp": "2026-07-09T15:54:59.424234" + }, + "homo_sapiens - vcf.gz - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.summary.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test" + }, + "test.passing.vcf.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "2": [ + [ + { + "id": "test" + }, + "test.passing.vcf.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "3": [ + [ + { + "id": "test" + }, + "test.regions.bed.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "4": [ + [ + { + "id": "test" + }, + "test.regions.bed.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "5": [ + [ + { + "id": "test" + }, + "test.failed_regions.bed.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "6": [ + [ + { + "id": "test" + }, + "test.failed_regions.bed.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "7": [ + [ + { + "id": "test" + }, + "test.cli_settings.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "8": [ + [ + "AARDVARK_MERGE", + "aardvark", + "0.10.5" + ] + ], + "failed_regions": [ + [ + { + "id": "test" + }, + "test.failed_regions.bed.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "failed_regions_index": [ + [ + { + "id": "test" + }, + "test.failed_regions.bed.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "passing_regions": [ + [ + { + "id": "test" + }, + "test.regions.bed.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "passing_regions_index": [ + [ + { + "id": "test" + }, + "test.regions.bed.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "passing_vcf": [ + [ + { + "id": "test" + }, + "test.passing.vcf.gz:md5,68b329da9893e34099c7d8ad5cb9c940" + ] + ], + "passing_vcf_index": [ + [ + { + "id": "test" + }, + "test.passing.vcf.gz.tbi:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "runinfo": [ + [ + { + "id": "test" + }, + "test.cli_settings.json:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "summary": [ + [ + { + "id": "test" + }, + "test.summary.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_aardvark": [ + [ + "AARDVARK_MERGE", + "aardvark", + "0.10.5" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.5" + }, + "timestamp": "2026-07-09T15:55:08.499158" + } +} \ No newline at end of file diff --git a/modules/nf-core/aardvark/merge/tests/nextflow.config b/modules/nf-core/aardvark/merge/tests/nextflow.config new file mode 100644 index 000000000000..29d8bed682e8 --- /dev/null +++ b/modules/nf-core/aardvark/merge/tests/nextflow.config @@ -0,0 +1,6 @@ +process { + withName: AARDVARK_MERGE { + ext.args = '--merge-strategy all --enable-no-conflict' + } + +} From c2926d02666c5555426e34d333ca068243170120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=BCbra=20Narc=C4=B1?= Date: Fri, 10 Jul 2026 11:33:41 +0200 Subject: [PATCH 2/3] Apply suggestion from @georgiakes Co-authored-by: Georgia Kesisoglou --- modules/nf-core/aardvark/merge/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/aardvark/merge/main.nf b/modules/nf-core/aardvark/merge/main.nf index cd923c286b62..24ecb1b09f63 100644 --- a/modules/nf-core/aardvark/merge/main.nf +++ b/modules/nf-core/aardvark/merge/main.nf @@ -29,7 +29,7 @@ process AARDVARK_MERGE { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def inputs = [vcfs].flatten().collect { "--input-vcf ${it}" }.join(' ') + def inputs = vcfs.flatten().collect { file -> "--input-vcf ${file}" }.join(' ') """ aardvark merge \\ From 6fe63b2e53228f527247e4086d666e45a668ebe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=BCbra=20Narc=C4=B1?= Date: Fri, 10 Jul 2026 13:19:10 +0200 Subject: [PATCH 3/3] Update modules/nf-core/aardvark/merge/main.nf Co-authored-by: Georgia Kesisoglou --- modules/nf-core/aardvark/merge/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/aardvark/merge/main.nf b/modules/nf-core/aardvark/merge/main.nf index 24ecb1b09f63..5824e2d0021f 100644 --- a/modules/nf-core/aardvark/merge/main.nf +++ b/modules/nf-core/aardvark/merge/main.nf @@ -29,7 +29,7 @@ process AARDVARK_MERGE { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ?: "${meta.id}" - def inputs = vcfs.flatten().collect { file -> "--input-vcf ${file}" }.join(' ') + def inputs = vcfs.collect { file -> "--input-vcf ${file}" }.join(' ') """ aardvark merge \\