diff --git a/modules/ensembl/infernal/cmscan/environment.yml b/modules/ensembl/infernal/cmscan/environment.yml new file mode 100644 index 0000000..9a2ef2f --- /dev/null +++ b/modules/ensembl/infernal/cmscan/environment.yml @@ -0,0 +1,6 @@ +--- +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::infernal=1.1.5 diff --git a/modules/ensembl/infernal/cmscan/main.nf b/modules/ensembl/infernal/cmscan/main.nf new file mode 100644 index 0000000..9cea45f --- /dev/null +++ b/modules/ensembl/infernal/cmscan/main.nf @@ -0,0 +1,74 @@ +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +nextflow.enable.types = true + +process CMSCAN { + tag "${meta.id}" + label 'process_high' + + conda "bioconda::infernal=1.1.5" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/infernal:1.1.5--pl5321h7b50bb2_4' : + 'quay.io/biocontainers/infernal:1.1.5--pl5321h7b50bb2_4' }" + + input: + record( + meta: Map, + chunk: Path, + rfam_filtered_cm: Path + ) + + output: + record( + meta: meta, + tblout: file("*.tblout") + ) + + topic: + tuple( + task.process, + 'infernal', + eval("cmscan -h 2>&1 | sed -nE 's/^# INFERNAL ([^ ]+).*/\\1/p'") + ) >> 'versions' + + script: + def prefix = task.ext.prefix + ? "${task.ext.prefix}.${meta.id}.${task.index}" + : "${meta.id}.${task.index}" + """ + cmpress ${rfam_filtered_cm} + cmscan --rfam --nohmmonly --cut_ga \\ + --notextw \\ + --fmt 2 \\ + --cpu ${task.cpus} \\ + --tblout ${prefix}.tblout \\ + ${rfam_filtered_cm} \\ + ${chunk} + + """ + + stub: + def prefix = task.ext.prefix + ? "${task.ext.prefix}.${meta.id}.${task.index}" + : "${meta.id}.${task.index}" + """ + touch ${prefix}.tblout + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + infernal: "stub" + END_VERSIONS + """ +} diff --git a/modules/ensembl/infernal/cmscan/meta.yml b/modules/ensembl/infernal/cmscan/meta.yml new file mode 100644 index 0000000..50fb7ec --- /dev/null +++ b/modules/ensembl/infernal/cmscan/meta.yml @@ -0,0 +1,40 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/meta-schema.json +name: CMSCAN +description: Search genome FASTA chunks against an Rfam covariance model database with Infernal cmscan. +keywords: + - infernal + - cmscan + - rfam + - covariance model +tools: + - infernal: + description: Infernal RNA homology search and alignment tools. + homepage: http://eddylab.org/infernal/ + documentation: http://eddylab.org/infernal/ + licence: ["BSD-3-Clause"] +input: + - - meta: + type: map + description: Groovy Map containing sample information, including a unique id. + - chunk: + type: file + description: FASTA chunk to scan. + pattern: "*.{fa,fasta,fna}" + - rfam_filtered_cm: + type: file + description: Rfam covariance model database used for scanning. + pattern: "*.cm{,.gz}" +output: + tblout: + - - meta: + type: map + description: Groovy Map containing sample information. + - "*.tblout": + type: file + description: Tabular cmscan hits for the input chunk. + pattern: "*.tblout" + versions: + - versions.yml: + type: file + description: File containing software versions. + pattern: "versions.yml" diff --git a/modules/ensembl/infernal/cmscan/tests/main.nf.test b/modules/ensembl/infernal/cmscan/tests/main.nf.test new file mode 100644 index 0000000..e30908a --- /dev/null +++ b/modules/ensembl/infernal/cmscan/tests/main.nf.test @@ -0,0 +1,72 @@ +// See the NOTICE file distributed with this work for additional information +// regarding copyright ownership. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +nextflow_process { + + name "Test Process CMSCAN" + script "../main.nf" + process "CMSCAN" + + tag "modules" + tag "modules_local" + tag "infernal" + tag "cmscan" + + test("should produce a cmscan tblout file") { + + options "-stub-run" + + when { + process { + """ + chunk_file = Channel.of( + '>test', + 'ACGTACGTACGT' + ) + .collectFile(name: 'test_chunk.fa', newLine: true) + + rfam_cm_file = Channel.of( + 'INFERNAL 1.1', + 'NAME test_model', + 'ACC RF00001', + 'GA 10.0', + '//' + ) + .collectFile(name: 'rfam_filtered.cm', newLine: true) + + input[0] = chunk_file + .combine(rfam_cm_file) + .map { chunk, rfam_cm -> + record( + meta: [id: 'test'], + chunk: chunk, + rfam_filtered_cm: rfam_cm + ) + } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.size() == 1 }, + { assert process.out[0][0].meta.id == 'test' }, + { assert path(process.out[0][0].tblout instanceof List ? process.out[0][0].tblout[0] : process.out[0][0].tblout).fileName.toString().endsWith('.tblout') }, + { assert snapshot(process.out).match() } + ) + } + } +} diff --git a/modules/ensembl/infernal/cmscan/tests/main.nf.test.snap b/modules/ensembl/infernal/cmscan/tests/main.nf.test.snap new file mode 100644 index 0000000..be70121 --- /dev/null +++ b/modules/ensembl/infernal/cmscan/tests/main.nf.test.snap @@ -0,0 +1,21 @@ +{ + "should produce a cmscan tblout file": { + "content": [ + { + "0": [ + { + "meta": { + "id": "test" + }, + "tblout": "test.1.tblout:md5,d41d8cd98f00b204e9800998ecf8427e" + } + ] + } + ], + "timestamp": "2026-09-25T18:22:53.008883237", + "meta": { + "nf-test": "0.9.5", + "nextflow": "26.04.0" + } + } +} \ No newline at end of file