diff --git a/modules/nf-core/pcne/environment.yml b/modules/nf-core/pcne/environment.yml new file mode 100644 index 00000000000..bb2a025557d --- /dev/null +++ b/modules/nf-core/pcne/environment.yml @@ -0,0 +1,6 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - "bioconda::pcne=3.3.1" diff --git a/modules/nf-core/pcne/main.nf b/modules/nf-core/pcne/main.nf new file mode 100644 index 00000000000..df273e52797 --- /dev/null +++ b/modules/nf-core/pcne/main.nf @@ -0,0 +1,49 @@ +process PCNE { + tag "${meta.id}" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://depot.galaxyproject.org/singularity/pcne%3A3.3.1--hdfd78af_0' + : 'quay.io/biocontainers/pcne:3.3.1--hdfd78af_0' }" + + input: + tuple val(meta), path(reads) + tuple val(meta2), path(chromosome) + tuple val(meta3), path(plasmids) + + output: + tuple val(meta), path("*_results.tsv"), emit: results + tuple val(meta), path("*.log"), emit: log + tuple val(meta), path("*.png"), emit: plots, optional: true + tuple val("${task.process}"), val('pcne'), eval("pcne -v | grep 'version' | tail -n 1 | sed 's/.*version //'"), topic: versions, emit: versions_pcne + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + + def is_bam = reads.toString().endsWith('.bam') + def input_cmd = is_bam ? "-b ${reads}" : "-r ${reads[0]} -R ${reads[1]}" + + def plasmid_cmd = plasmids instanceof List ? plasmids.join(' ') : plasmids + + """ + pcne \\ + -c ${chromosome} \\ + -p ${plasmid_cmd} \\ + ${input_cmd} \\ + -o ${prefix} \\ + -t ${task.cpus} \\ + ${args} + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}_results.tsv + touch ${prefix}.log + """ +} diff --git a/modules/nf-core/pcne/meta.yml b/modules/nf-core/pcne/meta.yml new file mode 100644 index 00000000000..38d1e311b1e --- /dev/null +++ b/modules/nf-core/pcne/meta.yml @@ -0,0 +1,110 @@ +name: "pcne" +description: "Estimates plasmid copy number from assembled genome" +keywords: + - plasmid + - copy number + - genomics + - alignment + - coverage +tools: + - "pcne": + description: "Estimates plasmid copy number from assembled genome." + homepage: "https://github.com/riccabolla/PCNE" + documentation: "https://github.com/riccabolla/PCNE" + tool_dev_url: "https://github.com/riccabolla/PCNE" + doi: "10.1177/11779322251410037" + licence: + - "MIT" + identifier: "" +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - reads: + type: file + description: FASTQ reads (paired or single) or a pre-aligned BAM file + pattern: "*.{fastq.gz,fq.gz,fastq,fq,bam}" + ontologies: + - edam: "http://edamontology.org/format_1930" + - edam: "http://edamontology.org/format_2572" + - - meta2: + type: map + description: | + Groovy Map containing reference chromosome information + e.g. `[ id:'genome' ]` + - chromosome: + type: file + description: Chromosome contigs FASTA file + pattern: "*.{fasta,fa,fasta.gz,fa.gz}" + ontologies: + - edam: "http://edamontology.org/format_1929" + - - meta3: + type: map + description: | + Groovy Map containing reference plasmid information + e.g. `[ id:'plasmids' ]` + - plasmids: + type: file + description: One or more plasmid FASTA files + pattern: "*.{fasta,fa,fasta.gz,fa.gz}" + ontologies: + - edam: "http://edamontology.org/format_1929" +output: + results: + - - meta: + type: map + description: Groovy Map containing sample information + - "*_results.tsv": + type: file + description: TSV file containing the estimated plasmid copy numbers + pattern: "*_results.tsv" + ontologies: + - edam: "http://edamontology.org/format_3475" + log: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.log": + type: file + description: PCNE run log file + pattern: "*.log" + ontologies: + - edam: "http://edamontology.org/format_2330" + plots: + - - meta: + type: map + description: Groovy Map containing sample information + - "*.png": + type: file + description: Bar plot of plasmid copy numbers or GC vs Depth diagnostic + plots + pattern: "*.png" + ontologies: + - edam: "http://edamontology.org/format_3603" + versions_pcne: + - - "${task.process}": + type: string + description: The name of the process + - "pcne": + type: string + description: The name of the tool + - "pcne -v | grep 'version' | tail -n 1 | sed 's/.*version //'": + type: eval + description: The expression to obtain the version of the tool +topics: + versions: + - - "${task.process}": + type: string + description: The name of the process + - "pcne": + type: string + description: The name of the tool + - "pcne -v | grep 'version' | tail -n 1 | sed 's/.*version //'": + type: eval + description: The expression to obtain the version of the tool +authors: + - "@riccabolla" +maintainers: + - "@riccabolla" diff --git a/modules/nf-core/pcne/tests/main.nf.test b/modules/nf-core/pcne/tests/main.nf.test new file mode 100644 index 00000000000..29471059bc3 --- /dev/null +++ b/modules/nf-core/pcne/tests/main.nf.test @@ -0,0 +1,69 @@ +nextflow_process { + + name "Test Process PCNE" + script "../main.nf" + process "PCNE" + + tag "modules" + tag "modules_nfcore" + tag "pcne" + + test("sarscov2 - bam") { + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id: 'genome' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = [ + [ id: 'transcriptome' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + assert snapshot(sanitizeOutput(process.out)).match() + } + + } + + test("sarscov2 - bam - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test', single_end:false ], // meta map + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/bam/test.paired_end.sorted.bam', checkIfExists: true) + ] + input[1] = [ + [ id: 'genome' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/genome.fasta', checkIfExists: true) + ] + input[2] = [ + [ id: 'transcriptome' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/genome/transcriptome.fasta', checkIfExists: true) + ] + """ + } + } + + then { + assert process.success + assert snapshot(sanitizeOutput(process.out)).match() + } + + } + +} diff --git a/modules/nf-core/pcne/tests/main.nf.test.snap b/modules/nf-core/pcne/tests/main.nf.test.snap new file mode 100644 index 00000000000..bb13c563247 --- /dev/null +++ b/modules/nf-core/pcne/tests/main.nf.test.snap @@ -0,0 +1,80 @@ +{ + "sarscov2 - bam - stub": { + "content": [ + { + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "plots": [ + + ], + "results": [ + [ + { + "id": "test", + "single_end": false + }, + "test_results.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions_pcne": [ + [ + "PCNE", + "pcne", + "3.3.1" + ] + ] + } + ], + "timestamp": "2026-04-29T17:10:13.997705663", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "sarscov2 - bam": { + "content": [ + { + "log": [ + [ + { + "id": "test", + "single_end": false + }, + "test.log:md5,9b282212a32df78088bdcb7a173df4ce" + ] + ], + "plots": [ + + ], + "results": [ + [ + { + "id": "test", + "single_end": false + }, + "test_results.tsv:md5,2efc4a2d2c671eeda63ce2a4aeb81fc6" + ] + ], + "versions_pcne": [ + [ + "PCNE", + "pcne", + "3.3.1" + ] + ] + } + ], + "timestamp": "2026-04-29T17:09:56.768899583", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + } +}