Skip to content

Commit a55a32e

Browse files
JonahnkiSPPearce
andauthored
New module: GRIMER (#11663)
* Add GRIMER module for interactive metagenome contamination visualisation * fix: use existing test-datasets file for stub test * fix: restore meta2/meta3 input descriptions, rename optional inputs, add stub snapshot, revert .nf-core.yml * fix(grimer): address reviewer comments - rename optional inputs, fix meta.yml, update tests * fix(grimer): fix version capture to strip ASCII banner * fix: resolve multi-line string interpolation issues in grimer test stub * fix: use workDir.resolve for on-the-fly test file creation * fix(grimer): fix version eval and regenerate snapshot * fix(grimer): fix version eval to strip ASCII banner, update meta.yml and snapshot * fix: add versions to placeholder snapshot to satisfy lint * fix: apply SPPearce suggested assertion pattern - snapshot filename and versions only * test: regenerate snapshot with real GRIMER output * fix: strip grimer prefix from version string in eval * fix: strip grimer prefix from version string, update snapshot, sync meta.yml --------- Co-authored-by: Simon Pearce <24893913+SPPearce@users.noreply.github.com>
1 parent ecd5df5 commit a55a32e

5 files changed

Lines changed: 263 additions & 0 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json
3+
channels:
4+
- conda-forge
5+
- bioconda
6+
dependencies:
7+
- "bioconda::grimer=1.1.0"

modules/nf-core/grimer/main.nf

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
process GRIMER {
2+
tag "$meta.id"
3+
label 'process_single'
4+
5+
conda "${moduleDir}/environment.yml"
6+
container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ?
7+
'https://depot.galaxyproject.org/singularity/grimer:1.1.0--pyhdfd78af_0':
8+
'quay.io/biocontainers/grimer:1.1.0--pyhdfd78af_0' }"
9+
10+
input:
11+
tuple val(meta), path(input_table)
12+
path sample_metadata
13+
path config
14+
15+
output:
16+
tuple val(meta), path("*.html"), emit: report
17+
tuple val("${task.process}"), val('grimer'), eval('grimer --version 2>&1 | tail -1 | sed "s/grimer //"'), emit: versions_grimer, topic: versions
18+
19+
when:
20+
task.ext.when == null || task.ext.when
21+
22+
script:
23+
def args = task.ext.args ?: ''
24+
def prefix = task.ext.prefix ?: "${meta.id}"
25+
def m_arg = sample_metadata ? "-m ${sample_metadata}" : ''
26+
def c_arg = config ? "-c ${config}" : ''
27+
"""
28+
grimer \\
29+
-i ${input_table} \\
30+
${m_arg} \\
31+
${c_arg} \\
32+
-o ${prefix}.html \\
33+
${args}
34+
"""
35+
36+
stub:
37+
def prefix = task.ext.prefix ?: "${meta.id}"
38+
"""
39+
touch ${prefix}.html
40+
"""
41+
}

modules/nf-core/grimer/meta.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: grimer
2+
description: |
3+
Generates an interactive HTML dashboard integrating taxonomy,
4+
annotation, and metadata to detect contamination in metagenomic
5+
and amplicon sequencing datasets. GRIMER is independent of
6+
quantification methods and directly analyses contingency tables.
7+
keywords:
8+
- metagenomics
9+
- contamination
10+
- visualisation
11+
- taxonomy
12+
- viromics
13+
- microbiome
14+
- dashboard
15+
tools:
16+
- grimer:
17+
description: |
18+
GRIMER performs automated contamination analysis and generates
19+
portable interactive dashboards from contingency tables,
20+
integrating taxonomy, annotation and metadata.
21+
homepage: https://github.com/pirovc/grimer
22+
documentation: https://pirovc.github.io/grimer/
23+
tool_dev_url: https://github.com/pirovc/grimer
24+
doi: "10.1101/2021.06.22.449360"
25+
licence:
26+
- "MIT"
27+
identifier: biotools:grimer
28+
args_id: "$args"
29+
input:
30+
- - meta:
31+
type: map
32+
description: |
33+
Groovy Map containing sample information.
34+
e.g. [ id:'sample1' ]
35+
- input_table:
36+
type: file
37+
description: |
38+
Tab-separated count/observation table or .biom file.
39+
Rows are observations; columns are samples.
40+
pattern: "*.{tsv,biom}"
41+
ontologies:
42+
- edam: http://edamontology.org/format_3475
43+
- edam: http://edamontology.org/format_3746
44+
- sample_metadata:
45+
type: file
46+
description: Tab-separated metadata file. Rows are samples; columns are
47+
metadata fields. Optional, pass [] to omit.
48+
pattern: "*.tsv"
49+
ontologies:
50+
- edam: http://edamontology.org/format_3475
51+
- config:
52+
type: file
53+
description: |
54+
YAML configuration file defining external tool references,
55+
controls, and annotations. Optional, pass [] to omit.
56+
pattern: "*.{yml,yaml}"
57+
ontologies:
58+
- edam: http://edamontology.org/format_3750
59+
output:
60+
report:
61+
- - meta:
62+
type: map
63+
description: Groovy Map containing sample information.
64+
- "*.html":
65+
type: file
66+
description: |
67+
Interactive HTML dashboard report integrating taxonomy,
68+
contamination analysis, heatmaps, and correlation plots.
69+
pattern: "*.html"
70+
ontologies: []
71+
versions_grimer:
72+
- - ${task.process}:
73+
type: string
74+
description: The name of the process
75+
- grimer:
76+
type: string
77+
description: The name of the tool
78+
- grimer --version 2>&1 | tail -1 | sed "s/grimer //":
79+
type: eval
80+
description: The expression to obtain the version of the tool
81+
topics:
82+
versions:
83+
- - ${task.process}:
84+
type: string
85+
description: The name of the process
86+
- grimer:
87+
type: string
88+
description: The name of the tool
89+
- grimer --version 2>&1 | tail -1 | sed "s/grimer //":
90+
type: eval
91+
description: The expression to obtain the version of the tool
92+
authors:
93+
- "@Jonahnki"
94+
maintainers:
95+
- "@Jonahnki"
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
nextflow_process {
2+
3+
name "Test Process GRIMER"
4+
script "../main.nf"
5+
process "GRIMER"
6+
7+
tag "modules"
8+
tag "modules_nfcore"
9+
tag "grimer"
10+
11+
test("grimer - tsv - basic") {
12+
13+
when {
14+
process {
15+
"""
16+
def count_table = file(workDir.resolve("test_count_table.tsv").toString())
17+
count_table.text = [
18+
"#OTU_ID\tsample1\tsample2\tsample3",
19+
"Bacteria;Proteobacteria\t1250\t890\t2100",
20+
"Bacteria;Firmicutes\t430\t1200\t320",
21+
"Viruses;Caudoviricetes\t45\t120\t88"
22+
].join("\\n") + "\\n"
23+
24+
input[0] = [
25+
[ id:"test_sample" ],
26+
count_table
27+
]
28+
input[1] = []
29+
input[2] = []
30+
"""
31+
}
32+
}
33+
34+
then {
35+
assert process.success
36+
assertAll(
37+
{ assert snapshot(
38+
file(process.out.report[0][1]).name,
39+
process.out.findAll { key, val -> key.startsWith("versions_") }
40+
).match() }
41+
)
42+
}
43+
}
44+
45+
test("grimer - tsv - stub") {
46+
47+
options "-stub"
48+
49+
when {
50+
process {
51+
"""
52+
def count_table = file(workDir.resolve("test_count_table.tsv").toString())
53+
count_table.text = [
54+
"#OTU_ID\tsample1\tsample2\tsample3",
55+
"Bacteria;Proteobacteria\t1250\t890\t2100",
56+
"Bacteria;Firmicutes\t430\t1200\t320",
57+
"Viruses;Caudoviricetes\t45\t120\t88"
58+
].join("\\n") + "\\n"
59+
60+
input[0] = [
61+
[ id:"test_stub" ],
62+
count_table
63+
]
64+
input[1] = []
65+
input[2] = []
66+
"""
67+
}
68+
}
69+
70+
then {
71+
assert process.success
72+
assertAll(
73+
{ assert snapshot(
74+
file(process.out.report[0][1]).name,
75+
process.out.findAll { key, val -> key.startsWith("versions_") }
76+
).match() }
77+
)
78+
}
79+
}
80+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"grimer - tsv - basic": {
3+
"content": [
4+
"test_sample.html",
5+
{
6+
"versions_grimer": [
7+
[
8+
"GRIMER",
9+
"grimer",
10+
"1.1.0"
11+
]
12+
]
13+
}
14+
],
15+
"timestamp": "2026-06-04T13:24:01.89404156",
16+
"meta": {
17+
"nf-test": "0.9.5",
18+
"nextflow": "25.04.6"
19+
}
20+
},
21+
"grimer - tsv - stub": {
22+
"content": [
23+
"test_stub.html",
24+
{
25+
"versions_grimer": [
26+
[
27+
"GRIMER",
28+
"grimer",
29+
"1.1.0"
30+
]
31+
]
32+
}
33+
],
34+
"timestamp": "2026-06-04T13:25:24.167541988",
35+
"meta": {
36+
"nf-test": "0.9.5",
37+
"nextflow": "25.04.6"
38+
}
39+
}
40+
}

0 commit comments

Comments
 (0)