Skip to content

New module: spoligotyper - #13085

Open
duceppemo wants to merge 3 commits into
nf-core:masterfrom
duceppemo:spoligotyper
Open

duceppemo wants to merge 3 commits into
nf-core:masterfrom
duceppemo:spoligotyper

Conversation

@duceppemo

Copy link
Copy Markdown

PR checklist

New module for spoligotyper (bioconda, docs): in silico spoligotyping of the Mycobacterium tuberculosis complex from reads (single or paired-end) or assemblies. Besides the spoligotype (binary, octal, hexadecimal, SB number), it reports the species from regions of difference, the lineage (Coll et al. 2014 barcode), the livestock lineages (Zwyer et al. 2021) and the lineage 1 sublineages (Netikul et al. 2022). Outputs: a table, JSON, a PDF report and a MultiQC custom content file.

nf-core test data has no M. tuberculosis complex genome, so the tests check that the module runs on the SARS-CoV-2 genome and reads and writes its outputs ("MTBC not detected" is the expected result for these data).

  • This comment contains a description of changes (with reason).
  • If you've fixed a bug or added code that should be tested, add tests!
  • If you've added a new tool - have you followed the module conventions in the contribution docs
  • If necessary, include test data in your PR. (Not needed: uses existing test data.)
  • Remove all TODO statements.
  • Broadcast software version numbers to topic: versions - See version_topics
  • Follow the naming conventions.
  • Follow the parameters requirements.
  • Follow the input/output options guidelines.
  • Add a resource label
  • Use BioConda and BioContainers if possible to fulfil software requirements.
  • Ensure that the test works with either Docker / Singularity. Conda CI tests can be quite flaky:
    • For modules:
      • nf-core modules test spoligotyper --profile docker
      • nf-core modules test spoligotyper --profile singularity (no Singularity on my machine, and the depot image is not mirrored yet)
      • nf-core modules test spoligotyper --profile conda

nf-core modules lint spoligotyper: 61 tests passed, 0 warnings, 0 failed.

🤖 Generated with Claude Code

In silico spoligotyping of the M. tuberculosis complex from reads or assemblies, with species
(regions of difference) and lineages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@vagkaratzas vagkaratzas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Blocking: the module still uses legacy biocontainers/depot containers; it needs a Seqera Wave build (nf-core modules containers create).
  • Blocking: the tests should snapshot sanitizeOutput(process.out) (with unstableKeys plus a stable check for unstable channels) instead of picking channels and file names; the paired-end test only snapshots versions.
  • Smaller points: use ${prefix} in the output paths, quote interpolated paths, and fix the meta.yml details (args_id, FASTQ/FASTA ontologies, "Optional" on the PDF).

Not run: G1 and G2. The PR's nf-core CI workflows (Run Linting, Run nf-test) have not run on the head commit and are waiting for maintainer approval (action_required), so there is no CI result to read. Please run nf-core modules lint spoligotyper and the tests with --profile +singularity; the PR description says the Singularity test was not run. G3 (nextflow lint) passes.

Diff 7.41/10 · Overall 7.41/10
nf-core-reviewer 0.3.0 / vagkaratzas-review (rubric v2) · claude-sonnet-5-5

Comment thread modules/nf-core/spoligotyper/main.nf Outdated
Comment on lines +6 to +8
container "${ workflow.containerEngine in ['singularity', 'apptainer'] && !task.ext.singularity_pull_docker_container ?
'https://depot.galaxyproject.org/singularity/spoligotyper:0.9.0--pyhdfd78af_0' :
'quay.io/biocontainers/spoligotyper:0.9.0--pyhdfd78af_0' }"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The container still points to legacy biocontainers / depot.galaxyproject.org. Please build a Seqera Wave container with nf-core modules containers create spoligotyper, which also adds the containers: block to meta.yml and the .conda-lock/ files.

Comment thread modules/nf-core/spoligotyper/main.nf Outdated
Comment on lines +14 to +17
tuple val(meta), path("*_spoligotyping.txt") , emit: tsv
tuple val(meta), path("*_spoligotyping.json") , emit: json
tuple val(meta), path("*_spoligotyping.pdf") , emit: pdf, optional: true
tuple val(meta), path("*_spoligotyping_mqc.json"), emit: multiqc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output names are predictable (--sample ${prefix} gives ${prefix}_spoligotyping.*), so use ${prefix} instead of globs.

Suggested change
tuple val(meta), path("*_spoligotyping.txt") , emit: tsv
tuple val(meta), path("*_spoligotyping.json") , emit: json
tuple val(meta), path("*_spoligotyping.pdf") , emit: pdf, optional: true
tuple val(meta), path("*_spoligotyping_mqc.json"), emit: multiqc
tuple val(meta), path("${prefix}_spoligotyping.txt") , emit: tsv
tuple val(meta), path("${prefix}_spoligotyping.json") , emit: json
tuple val(meta), path("${prefix}_spoligotyping.pdf") , emit: pdf, optional: true
tuple val(meta), path("${prefix}_spoligotyping_mqc.json"), emit: multiqc

Comment thread modules/nf-core/spoligotyper/main.nf Outdated
def args = task.ext.args ?: ''
def prefix = task.ext.prefix ?: "${meta.id}"
// Reads (single-end or paired-end) or an assembly: spoligotyper detects the file type
def input = reads instanceof List && reads.size() == 2 ? "-r1 ${reads[0]} -r2 ${reads[1]}" : "-r1 ${reads}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quote the staged file names in case they contain spaces.

Suggested change
def input = reads instanceof List && reads.size() == 2 ? "-r1 ${reads[0]} -r2 ${reads[1]}" : "-r1 ${reads}"
def input = reads instanceof List && reads.size() == 2 ? "-r1 '${reads[0]}' -r2 '${reads[1]}'" : "-r1 '${reads}'"

Comment thread modules/nf-core/spoligotyper/main.nf Outdated
spoligotyper \\
$args \\
$input \\
--sample ${prefix} \\

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: quote the prefix.

Suggested change
--sample ${prefix} \\
--sample "${prefix}" \\

- genotyping
- lineage
tools:
- spoligotyper:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tool is missing args_id: "$args".

Comment thread modules/nf-core/spoligotyper/meta.yml Outdated
e.g. [ id:'test', single_end:false ]
- "*_spoligotyping.pdf":
type: file
description: PDF report for quality assurance (not written with --no-pdf)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PDF output is optional (optional: true in main.nf), so the description should say "Optional".

Suggested change
description: PDF report for quality assurance (not written with --no-pdf)
description: Optional PDF report for quality assurance (not written with --no-pdf)


// nf-core test data has no M. tuberculosis complex genome: these tests check that the module runs and
// writes its outputs ("MTBC not detected" is the expected result).
test("sarscov2 - fasta") {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put a bare assert process.success before assertAll(...), as in the nf-core template (same for the other two tests).

Comment on lines +28 to +33
{ assert snapshot(
file(process.out.pdf[0][1]).name,
file(process.out.json[0][1]).name,
process.out.multiqc,
process.out.findAll { key, val -> key.startsWith('versions') }
).match() }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not hand-pick channels and file names. Snapshot sanitizeOutput(process.out) and list only the truly unstable channels (the PDF and the JSON with run information, if they change between runs) in unstableKeys. Give each exempted channel back a stable check in the same snapshot(...), e.g. .contains() on a line the tool always writes.

assertAll(
{ assert process.success },
{ assert path(process.out.tsv[0][1]).text.contains('fastq') },
{ assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test only snapshots the versions, so the paired-end branch is not checked against its outputs. Use snapshot(sanitizeOutput(process.out, unstableKeys: [...])) with the same stable checks as above.

then {
assertAll(
{ assert process.success },
{ assert snapshot(process.out).match() }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap the output with sanitizeOutput.

Suggested change
{ assert snapshot(process.out).match() }
{ assert snapshot(sanitizeOutput(process.out)).match() }

@vagkaratzas

Copy link
Copy Markdown
Contributor

CI only runs automatically for nf-core members. Please ask for a GitHub invitation in the nf-core Slack #github-invitations channel; once you've joined, CI will run on your next push.

Comment added by Claude

- Seqera Wave containers (nf-core modules containers create) instead of
  the legacy biocontainers/depot images, with the conda lock files
- Tests snapshot sanitizeOutput(process.out) with unstableKeys for the
  json and pdf channels (they embed run timestamps), plus stable content
  checks on those channels; snapshot regenerated
- ${prefix} in the output paths, quoted interpolated paths
- meta.yml: args_id, FASTQ/FASTA ontologies on the input, 'Optional.' on
  the pdf output, ${prefix} output names

nf-core modules lint: 79 passed, 0 warnings, 0 failed.
nf-test passes with --profile docker and --profile singularity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added size/xl and removed size/m labels Oct 27, 2026
@github-actions

Copy link
Copy Markdown

This PR exceeds the recommended size of 1000 lines. Please make sure you are NOT addressing multiple issues with one PR. Note this PR might be rejected due to its size.

@duceppemo

Copy link
Copy Markdown
Author

Thanks for the review @vagkaratzas — all points addressed in 009a860:

  • Containers: switched to Seqera Wave builds via nf-core modules containers create (amd64/arm64 docker + singularity, conda lock files included).
  • Tests: all tests now snapshot sanitizeOutput(process.out, unstableKeys: ["json", "pdf"]) (those two outputs embed run timestamps), with stable content checks on the unstable channels; the paired-end test now covers the full output. Snapshot regenerated.
  • Smaller points: ${prefix} in the output paths, quoted interpolated paths, and the meta.yml fixes (args_id, FASTQ/FASTA ontologies on the input, "Optional." on the PDF).

Verified locally: nf-core modules lint spoligotyper passes (79 passed, 0 warnings, 0 failed), and nf-test passes with both --profile docker and --profile singularity.

The CI workflows may still need maintainer approval to run on this PR.

@vagkaratzas

Copy link
Copy Markdown
Contributor

CI only runs automatically for nf-core members. Please ask for a GitHub invitation in the nf-core Slack #github-invitations channel; once you've joined, CI will run on your next push.

Comment added by Claude

@duceppemo can you do the above so you become a member of the nf-core organization, in order to have the tests on the ci run?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants