diff --git a/modules/nf-core/cmaple/environment.yml b/modules/nf-core/cmaple/environment.yml new file mode 100644 index 000000000000..58961a36d5ac --- /dev/null +++ b/modules/nf-core/cmaple/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::cmaple=1.1.0 diff --git a/modules/nf-core/cmaple/main.nf b/modules/nf-core/cmaple/main.nf new file mode 100644 index 000000000000..07eabadd2454 --- /dev/null +++ b/modules/nf-core/cmaple/main.nf @@ -0,0 +1,53 @@ +process CMAPLE { + 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/cmaple:1.1.0--h503566f_1': + 'biocontainers/cmaple:1.1.0--h503566f_1' }" + + input: + tuple val(meta), path(aln), path(newick) + + output: + tuple val(meta), path("*.treefile"), emit: treefile + tuple val(meta), path("*.log") , emit: log + path "versions.yml" , emit: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + def tree_arg = newick ? "-t ${newick}" : "" + """ + cmaple-aa \\ + $args \\ + -nt $task.cpus \\ + --prefix ${prefix} \\ + ${tree_arg} \\ + -aln $aln + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cmaple: \$(cmaple --help | grep -m1 'CMAPLE version' | sed -E 's/.*version ([0-9.]+).*/\\1/') + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + echo $args + + touch ${prefix}.treefile + touch ${prefix}.log + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + cmaple: \$(cmaple --help | grep -m1 'CMAPLE version' | sed -E 's/.*version ([0-9.]+).*/\\1/') + END_VERSIONS + """ +} diff --git a/modules/nf-core/cmaple/meta.yml b/modules/nf-core/cmaple/meta.yml new file mode 100644 index 000000000000..733e8581bf78 --- /dev/null +++ b/modules/nf-core/cmaple/meta.yml @@ -0,0 +1,82 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: cmaple +description: Efficient phylogenetic tree reconstruction for sequences using the CMAPLE algorithm +keywords: + - phylogeny + - phylogenetic tree + - maximum likelihood + - dna + - amino acid + - alignment + - tree reconstruction + - cmaple + - iqtree +tools: + - cmaple: + description: | + CMAPLE (Comprehensive Maximum-likelihood Analysis for Phylogenetic Likelihood Estimation) + is an efficient implementation of the MAPLE algorithm for phylogenetic tree reconstruction, + particularly optimized for pathogen sequences with low divergence such as SARS-CoV-2. + It is integrated within IQ-TREE. + homepage: "https://github.com/iqtree/cmaple" + documentation: "https://github.com/iqtree/cmaple/wiki/User-Manual" + tool_dev_url: "https://github.com/iqtree/cmaple" + doi: "10.1093/molbev/msae134" + licence: ["GPL-2.0"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - aln: + type: file + description: Multiple sequence alignment file in FASTA, PHYLIP, or MAPLE format + pattern: "*.{fa,fasta,faa,fna,fas,aln,afa,phy,phylip,maple}" + - newick: + type: file + description: A Newick formatted tree based on multiple sequence alignment + pattern: "*.{newick,nwk,treefile}" + ontologies: + - edam: http://edamontology.org/format_1910 # newick + +output: + treefile: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*.treefile": + type: file + description: Maximum likelihood phylogenetic tree in Newick format + pattern: "*.treefile" + ontologies: + - edam: http://edamontology.org/format_1910 # newick + log: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1', single_end:false ]` + - "*.log": + type: file + description: Log file containing detailed information about the tree reconstruction process + pattern: "*.log" + ontologies: + - edam: "http://edamontology.org/format_2330" # Textual format + + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + +authors: + - "@vagkaratzas" +maintainers: + - "@vagkaratzas" diff --git a/modules/nf-core/cmaple/tests/main.nf.test b/modules/nf-core/cmaple/tests/main.nf.test new file mode 100644 index 000000000000..836a4f6c024c --- /dev/null +++ b/modules/nf-core/cmaple/tests/main.nf.test @@ -0,0 +1,106 @@ +nextflow_process { + + name "Test Process CMAPLE" + script "../main.nf" + process "CMAPLE" + + tag "modules" + tag "modules_nfcore" + tag "cmaple" + tag "gunzip" + + test("seatoxin - aa - aln") { + + when { + process { + """ + input[0] = [ + [ id:'test_aa' ], + file(params.modules_testdata_base_path + 'genomics/eukaryotes/anemonia_sulcata/seatoxin-ref.aln', checkIfExists: true), + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.log[0][1]).name, + process.out.treefile, + process.out.versions.collect{ path(it).yaml } + ).match() } + ) + } + + } + + test("haemophilus_influenzae - dna - newick - aln") { + + setup { + run("GUNZIP") { + script "../../gunzip/main.nf" + process { + """ + input[0] = [ + [ id: 'test_gunzip' ], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/haemophilus_influenzae/genome/genome.aln.gz', checkIfExists: true) + ] + """ + } + } + } + + when { + process { + """ + input[0] = GUNZIP.out.gunzip.map{[ + [ id: 'test_dna' ], + it[1], + file(params.modules_testdata_base_path + 'genomics/prokaryotes/haemophilus_influenzae/genome/genome.aln.nwk', checkIfExists: true) + ]} + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot( + file(process.out.log[0][1]).name, + process.out.treefile, + process.out.versions.collect{ path(it).yaml } + ).match() } + ) + } + + } + + test("seatoxin - aa - aln - stub") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test_stub' ], + file(params.modules_testdata_base_path + 'genomics/eukaryotes/anemonia_sulcata/seatoxin-ref.aln', checkIfExists: true), + [] + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() }, + { assert snapshot(process.out.versions).match("versions") } + ) + } + + } + +} diff --git a/modules/nf-core/cmaple/tests/main.nf.test.snap b/modules/nf-core/cmaple/tests/main.nf.test.snap new file mode 100644 index 000000000000..bf874d7e414b --- /dev/null +++ b/modules/nf-core/cmaple/tests/main.nf.test.snap @@ -0,0 +1,113 @@ +{ + "seatoxin - aa - aln - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test_stub" + }, + "test_stub.treefile:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + [ + { + "id": "test_stub" + }, + "test_stub.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "2": [ + "versions.yml:md5,975773bfb5d2679d2d0a78e1c5e1444a" + ], + "log": [ + [ + { + "id": "test_stub" + }, + "test_stub.log:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "treefile": [ + [ + { + "id": "test_stub" + }, + "test_stub.treefile:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,975773bfb5d2679d2d0a78e1c5e1444a" + ] + } + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-16T13:44:33.656447134" + }, + "haemophilus_influenzae - dna - newick - aln": { + "content": [ + "test_dna.log", + [ + [ + { + "id": "test_dna" + }, + "test_dna.treefile:md5,bbc5f987e523bda0335ae7a2d70b982c" + ] + ], + [ + { + "CMAPLE": { + "cmaple": "1.1.0" + } + } + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-16T13:44:26.501246515" + }, + "versions": { + "content": [ + [ + "versions.yml:md5,975773bfb5d2679d2d0a78e1c5e1444a" + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-16T13:44:33.677485714" + }, + "seatoxin - aa - aln": { + "content": [ + "test_aa.log", + [ + [ + { + "id": "test_aa" + }, + "test_aa.treefile:md5,e8d45477e64ac8aae9ebda4859acdaf1" + ] + ], + [ + { + "CMAPLE": { + "cmaple": "1.1.0" + } + } + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-16T13:44:18.090278163" + } +} \ No newline at end of file