diff --git a/modules/nf-core/finaletoolkit/delfi/environment.yml b/modules/nf-core/finaletoolkit/delfi/environment.yml new file mode 100644 index 000000000000..64701682a25a --- /dev/null +++ b/modules/nf-core/finaletoolkit/delfi/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::finaletoolkit=0.11.1" diff --git a/modules/nf-core/finaletoolkit/delfi/main.nf b/modules/nf-core/finaletoolkit/delfi/main.nf new file mode 100644 index 000000000000..32d2a056b613 --- /dev/null +++ b/modules/nf-core/finaletoolkit/delfi/main.nf @@ -0,0 +1,46 @@ +process FINALETOOLKIT_DELFI { + tag "${meta.id}" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34f01d128ed135aedc33ddb62fced3911bef6d1a909694291b7184bf83719402/data' + : 'community.wave.seqera.io/library/finaletoolkit:0.11.1--8fe5ba6ec9e2ec95'}" + + input: + tuple val(meta), path(bam), path(bai) + tuple val(meta2), path(genome_2bit) + tuple val(meta3), path(chromosome_sizes) + tuple val(meta4), path(bins) + + output: + tuple val(meta), path("*.bed"), emit: bed + tuple val("${task.process}"), val('finaletoolkit'), eval("finaletoolkit --version | sed 's/FinaleToolkit //g'"), topic: versions, emit: versions_finaletoolkit + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + finaletoolkit \\ + delfi \\ + -w ${task.cpus} \\ + ${bam} \\ + ${chromosome_sizes} \\ + ${genome_2bit} \\ + ${bins} \\ + ${args} \\ + -o "${prefix}_delfi.bed" + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + echo ${args} + + touch ${prefix}_delfi.bed + """ +} diff --git a/modules/nf-core/finaletoolkit/delfi/meta.yml b/modules/nf-core/finaletoolkit/delfi/meta.yml new file mode 100644 index 000000000000..03eedfc182a9 --- /dev/null +++ b/modules/nf-core/finaletoolkit/delfi/meta.yml @@ -0,0 +1,110 @@ +name: "finaletoolkit_delfi" +description: Generate a binned fragment profile and a fragment distribution histogram +keywords: + - sort + - genomics + - fragmentomics +tools: + - "finaletoolkit": + description: "Extract cfDNA fragmentation features from sequencing data." + homepage: "https://epifluidlab.github.io/FinaleToolkit/" + documentation: "https://epifluidlab.github.io/FinaleToolkit/documentation/index.html" + tool_dev_url: "https://github.com/epifluidlab/FinaleToolkit" + doi: "10.1093/bioadv/vbaf236" + licence: + - "MIT" + identifier: biotools:finaletoolkit +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - bam: + type: file + description: Sorted BAM file + pattern: "*.bam" + ontologies: + - edam: "http://edamontology.org/format_2572" + - bai: + type: file + description: BAM file index + pattern: "*.bai" + ontologies: + - edam: "http://edamontology.org/format_3327" + - - meta2: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - genome_2bit: + type: file + description: | + 2bit compressed genome file (must be the same as the one used for the + BAM file) + pattern: "*.2bit" + ontologies: + - edam: "http://edamontology.org/format_3009" + - - meta3: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - chromosome_sizes: + type: file + pattern: "*.sizes" + description: | + Two-column file containing the size for each chromosome + ontologies: + - edam: "http://edamontology.org/format_3475" + - - meta4: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - bins: + type: file + description: | + BED containing binned genomic coordinates + pattern: "*.bed" + ontologies: + - edam: "http://edamontology.org/format_3003" +output: + bed: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - "*.bed": + type: file + pattern: "*.bed" + description: | + BED file containing DELFI scores + ontologies: + - edam: "http://edamontology.org/format_3003" + versions_finaletoolkit: + - - ${task.process}: + type: string + description: The name of the process + - finaletoolkit: + type: string + description: The name of the tool + - "finaletoolkit --version | sed 's/FinaleToolkit //g'": + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - finaletoolkit: + type: string + description: The name of the tool + - "finaletoolkit --version | sed 's/FinaleToolkit //g'": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@lbeltrame" +maintainers: + - "@lbeltrame" diff --git a/modules/nf-core/finaletoolkit/delfi/tests/main.nf.test b/modules/nf-core/finaletoolkit/delfi/tests/main.nf.test new file mode 100644 index 000000000000..f856c6e7b3b7 --- /dev/null +++ b/modules/nf-core/finaletoolkit/delfi/tests/main.nf.test @@ -0,0 +1,100 @@ +nextflow_process { + + name "Test Process FINALETOOLKIT_DELFI" + script "../main.nf" + process "FINALETOOLKIT_DELFI" + + tag "modules" + tag "modules_nfcore" + tag "finaletoolkit" + tag "finaletoolkit/delfi" + + test("homo_sapiens - bam") { + + when { + + process { + + config "./nextflow.config" + + """ + input[0] = [ + [ id:'test' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/NA12878.chr22.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/NA12878.chr22.bam.bai', checkIfExists: true), + ] + input[1] = [ + [id: 'genome' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.2bit', checkIfExists: true) + , + ] + input[2] = [ + [id: 'sizes' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.sizes', checkIfExists: true), + ] + input[3] = [ + [id: 'bins' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.bins_10kb.bed', checkIfExists: true), + ] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + process.out, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match() } + ) + } + + } + + test("homo_sapiens - stub") { + + options "-stub" + + when { + + process { + + config "./nextflow.config" + + """ + input[0] = [ + [ id:'test' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/NA12878.chr22.bam', checkIfExists: true), + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/bam/NA12878.chr22.bam.bai', checkIfExists: true), + ] + input[1] = [ + [id: 'genome' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.2bit', checkIfExists: true) + , + ] + input[2] = [ + [id: 'sizes' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.sizes', checkIfExists: true), + ] + input[3] = [ + [id: 'bins' ], + file(params.modules_testdata_base_path + 'genomics/homo_sapiens/genome/genome.bins_10kb.bed', checkIfExists: true), + ] + """ + } + } + + then { + assert process.success + assertAll( + { assert snapshot( + process.out, + process.out.findAll { key, val -> key.startsWith("versions") } + ).match() } + ) + } + + } + +} diff --git a/modules/nf-core/finaletoolkit/delfi/tests/main.nf.test.snap b/modules/nf-core/finaletoolkit/delfi/tests/main.nf.test.snap new file mode 100644 index 000000000000..803c95e35bb2 --- /dev/null +++ b/modules/nf-core/finaletoolkit/delfi/tests/main.nf.test.snap @@ -0,0 +1,102 @@ +{ + "homo_sapiens - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_delfi.bed:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + "FINALETOOLKIT_DELFI", + "finaletoolkit", + "0.11.1" + ] + ], + "bed": [ + [ + { + "id": "test" + }, + "test_delfi.bed:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_finaletoolkit": [ + [ + "FINALETOOLKIT_DELFI", + "finaletoolkit", + "0.11.1" + ] + ] + }, + { + "versions_finaletoolkit": [ + [ + "FINALETOOLKIT_DELFI", + "finaletoolkit", + "0.11.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-05-06T14:45:08.530570524" + }, + "homo_sapiens - bam": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test_delfi.bed:md5,125dc88e57b66bf668a8961c81ede4a8" + ] + ], + "1": [ + [ + "FINALETOOLKIT_DELFI", + "finaletoolkit", + "0.11.1" + ] + ], + "bed": [ + [ + { + "id": "test" + }, + "test_delfi.bed:md5,125dc88e57b66bf668a8961c81ede4a8" + ] + ], + "versions_finaletoolkit": [ + [ + "FINALETOOLKIT_DELFI", + "finaletoolkit", + "0.11.1" + ] + ] + }, + { + "versions_finaletoolkit": [ + [ + "FINALETOOLKIT_DELFI", + "finaletoolkit", + "0.11.1" + ] + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.4" + }, + "timestamp": "2026-05-07T08:54:00.659731417" + } +} \ No newline at end of file diff --git a/modules/nf-core/finaletoolkit/delfi/tests/nextflow.config b/modules/nf-core/finaletoolkit/delfi/tests/nextflow.config new file mode 100644 index 000000000000..ce7d8dbb8565 --- /dev/null +++ b/modules/nf-core/finaletoolkit/delfi/tests/nextflow.config @@ -0,0 +1,9 @@ +process { + withName: 'FINALETOOLKIT_DELFI' { + // Chr22 is too small for meaningful data, so remove all filters + // We need 2 workers because otherwise there is a bug (fixed upstream, but without a new version) + // that breaks the program with only one worker + cpus = 2 + ext.args = "--no-merge-bins --no-gc-correct --quality-threshold 0" + } +}