Skip to content

New module: onkopus/run - #13387

Open
vagkaratzas wants to merge 7 commits into
masterfrom
onkopus-run
Open

vagkaratzas wants to merge 7 commits into
masterfrom
onkopus-run

Conversation

@vagkaratzas

@vagkaratzas vagkaratzas commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Adds onkopus/run, which annotates, interprets and prioritises cancer variants in a VCF with Onkopus (Kurz et al. 2025, NAR).

@famosab, since you opened #9211, could you review this? Thanks!

Notes for review

  • The module is named onkopus/run because the tool has several subcommands (run, install, start, list-modules, …).
  • Onkopus is only on PyPI, not bioconda or conda-forge. environment.yml therefore uses conda-forge python and pip with onkopus==0.7.0, and the containers are Seqera Containers built from it.
  • onkopus run sends variants to the public Onkopus web services. Tasks need internet access, and patient data leave the compute environment. Both points are documented in meta.yml. The real test therefore depends on that service: it annotates one variant (BRAF V600E) with -m clinvar and checks that a ClinVar field is added, instead of snapshotting a checksum.
  • Onkopus writes into its own install directory when imported, which fails in read-only Singularity images. The script copies the package into the work directory and puts it on PYTHONPATH.
  • Onkopus has no --version flag, so the version is read with importlib.metadata.
  • Inputs are tuple val(meta), path(vcf) and val genome (hg19, hg38 or t2t). The onkopus annotation modules (-m) and the liftover target genome (-t) go through ext.args.

Upstream limitations (to be reported to the Onkopus authors)

Onkopus v0.7.0: 7 issues found while packaging

Container/env: community.wave.seqera.io/library/python_pip_onkopus:cbfd43c4529368f9 (Seqera Containers), PyPI onkopus==0.7.0 (pulls adagenes==0.5.3)
Found while packaging the tool as an nf-core module.

1. Package writes into its own install directory at import

  • nf-core expectation: tools run from read-only containers (Singularity/Apptainer images) and write only to the working directory.
  • Actual behaviour: importing adagenes / onkopus creates directories next to the package source (adagenes/conf/uploaded_files, site-packages/data), which fails with "Permission denied" in a read-only image, even with --writable-tmpfs. onkopus --help fails for the same reason.
  • Workaround applied: the script copies both packages (~13 MB) into ./pylib and prepends it to PYTHONPATH (modules/nf-core/onkopus/run/main.nf:26-30).
  • Suggested upstream fix: create runtime/upload/data directories under a user-writable location (current directory, $TMPDIR or an ONKOPUS_DATA_DIR env variable), never inside the installed package.

2. No --version flag

  • nf-core expectation: the tool reports its version on the command line (onkopus --version).
  • Actual behaviour: no version flag or subcommand exists.
  • Workaround applied: version read via python -c "import importlib.metadata as m; print(m.version('onkopus'))" (main.nf:17).
  • Suggested upstream fix: add onkopus --version.

3. Default mode sends variant data to a public web service

  • nf-core expectation: modules run offline from their container.
  • Actual behaviour: onkopus run sends variants to https://mtb.bioinf.med.uni-goettingen.de; offline use needs Docker-run module servers (onkopus install / start), which cannot run inside a module container. Tests depend on the live service and its current annotation content.
  • Workaround applied: module uses the remote default; the internet and data-privacy caveat is documented in meta.yml; tests assert structure (a ClinVar field present) instead of file checksums (tests/main.nf.test).
  • Suggested upstream fix: allow pointing modules at local database files without Docker, or document a stable test endpoint/version for annotation content.

4. Compressed output not documented

  • nf-core expectation: tools can write compressed output (.vcf.gz) directly.
  • Actual behaviour: output format is taken from the -o extension; gzip output support is undocumented.
  • Workaround applied: write plain ${prefix}.tmp.vcf, then gzip it (main.nf:32-38).
  • Suggested upstream fix: support and document -o out.vcf.gz (bgzip).

5. Several -m modules may overwrite each other (from source, not tested)

  • nf-core expectation: -m a,b applies all selected modules to one output.
  • Actual behaviour: from the source, each module appears to re-read the original input and overwrite the output, so only the last module's annotations may survive.
  • Workaround applied: meta.yml advises one -m module per process; tests use -m clinvar only.
  • Suggested upstream fix: chain modules on the annotated data, or document the behaviour.

6. Liftover writes a temporary file with a trailing space in its name (from source, not tested)

  • nf-core expectation: intermediate files have predictable names or are cleaned up.
  • Actual behaviour: for hg19/t2t input a <input>.GRCh38.vcf file (trailing space) is written next to the input.
  • Workaround applied: none needed; it stays in the work directory and is not an output.
  • Suggested upstream fix: drop the trailing space and remove the temporary file after use.

7. Noisy SyntaxWarning on stderr

  • nf-core expectation: clean stderr on success.
  • Actual behaviour: adagenes emits Python SyntaxWarning messages (invalid escape sequences) on every run.
  • Workaround applied: none; harmless.
  • Suggested upstream fix: use raw strings for regex patterns in adagenes.

Generated by nf-core-module-dev v1.7.0 (Claude Opus 5.5, high effort, as manager; Claude Sonnet 5.5, medium effort, as subagents)

PR checklist

Closes #9211

  • 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. (The one-variant VCF is built inside the test, so no new test data is needed.)
  • 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. (Not possible: the tool is only on PyPI, so the module uses Seqera Containers.)
  • Ensure that the test works with either Docker / Singularity. Conda CI tests can be quite flaky:
    • For modules:
      • nf-core modules test <MODULE> --profile docker
      • nf-core modules test <MODULE> --profile singularity
      • nf-core modules test <MODULE> --profile conda

🤖 Generated with Claude Code

Annotate, interpret and prioritise cancer variants in a VCF with
Onkopus (https://gitlab.gwdg.de/MedBioinf/mtb/onkopus/onkopus).
Onkopus is only on PyPI, so the environment installs it with pip and
uses Seqera Containers. The tool queries the public Onkopus web
services, so the real test needs internet access.

Closes #9211

Generated by nf-core-module-dev v1.7.0 (Claude Opus 5.5, high effort,
as manager; Claude Sonnet 5.5, medium effort, as subagents)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@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.

@vagkaratzas vagkaratzas mentioned this pull request Oct 18, 2026
3 of 4 tasks
@famosab

famosab commented Oct 19, 2026

Copy link
Copy Markdown
Member

Upstream limitations (to be reported to the Onkopus authors)

Did you open an issue? Can you link it here?

@famosab famosab left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for picking this up :) just a few small comments

Comment thread modules/nf-core/onkopus/run/main.nf Outdated
Comment thread modules/nf-core/onkopus/run/main.nf Outdated
-g "${genome}" \\
${args}

gzip -c "${prefix}.tmp.vcf" > "${prefix}.ann.vcf.gz"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need vcf files to be bgzipped not only gzipped even though the extension is always only called .gz instead of .bgz.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in fd3b5b4: added bioconda::htslib=1.24 to the environment (containers rebuilt) and the script and stub now write the output with bgzip.

Comment added by Claude Opus 5.5

Comment thread modules/nf-core/onkopus/run/meta.yml
Comment thread modules/nf-core/onkopus/run/meta.yml Outdated
Comment on lines +36 to +40
description: Variant calls in VCF format, optionally gzip-compressed
pattern: "*.{vcf,vcf.gz}"
ontologies:
- edam: http://edamontology.org/format_3016 # VCF
- edam: http://edamontology.org/format_3989 # GZIP format

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we need bgzipped files here aswell.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in fd3b5b4: input now uses the bgzip EDAM term (format_3615); plain VCF is still accepted.

Comment added by Claude Opus 5.5

Comment thread modules/nf-core/onkopus/run/meta.yml Outdated
Comment on lines +53 to +57
description: Annotated variants in gzip-compressed VCF format
pattern: "*.ann.vcf.gz"
ontologies:
- edam: http://edamontology.org/format_3016 # VCF
- edam: http://edamontology.org/format_3989 # GZIP format

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we need bgzipped files here aswell.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in fd3b5b4: output now uses the bgzip EDAM term (format_3615).

Comment added by Claude Opus 5.5

Comment on lines +21 to +26
input[0] = channel.of(
"##fileformat=VCFv4.2",
"#CHROM\\tPOS\\tID\\tREF\\tALT\\tQUAL\\tFILTER\\tINFO",
"chr7\\t140753336\\t.\\tA\\tT\\t.\\t.\\t."
).collectFile(name: 'braf_v600e.vcf', newLine: true).map { f -> tuple([ id:'test' ], f) }
input[1] = 'hg38'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice way to test but I would like to see a full vcf being tested (can be with only a few variants but this is very simplified).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in fd3b5b4: the test now uses genomics/homo_sapiens/illumina/pharmcat/test.chr22.single.sample.vcf.gz from test-datasets (156 chr22 variants, 29 get ClinVar annotations; about 11 s against the Onkopus service). Smaller test VCFs had no ClinVar hits, so the snapshot would have shown no annotation.

Comment added by Claude Opus 5.5

Comment thread modules/nf-core/onkopus/run/tests/main.nf.test
@vagkaratzas
vagkaratzas marked this pull request as ready for review October 19, 2026 20:28
Address review on #13387:
- compress the annotated VCF with bgzip (htslib added; containers rebuilt)
- mark input/output VCF as bgzip (EDAM format_3615) in meta.yml
- test on a real hg38 VCF from test-datasets and snapshot its md5
- fix environment.yml indentation flagged by prettier

Generated by Claude Opus 5.5

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

Copy link
Copy Markdown
Contributor Author

Did you open an issue? Can you link it here?

Not yet: Onkopus is hosted on the GWDG GitLab (https://gitlab.gwdg.de/MedBioinf/mtb/onkopus/onkopus). The full list of limitations is in the PR description, ready to forward to the authors if you have a contact there.

Comment added by Claude Opus 5.5

@vagkaratzas
vagkaratzas requested a review from famosab October 19, 2026 21:00
).collectFile(name: 'braf_v600e.vcf', newLine: true).map { f -> tuple([ id:'test' ], f) }
input[0] = channel.of([
[ id:'test' ],
file(params.modules_testdata_base_path + 'genomics/homo_sapiens/illumina/pharmcat/test.chr22.single.sample.vcf.gz', checkIfExists: true)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why the pharmcat vcf? and a more generic one also used with VEP

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also I am surprised that the md5sum seems to be stable usually that is not the case with bgzipped vcfs and you have to assert them specifically so I am not sure if it works as expected

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

VEP's test VCF is SARS-CoV-2 (genomics/sarscov2/illumina/vcf/test.vcf), and Onkopus annotates human hg38 only, so it would come back with no annotation. The generic human test VCFs I tried had no ClinVar hits either, which makes for an empty snapshot. The pharmcat file is just a human hg38 chr22 VCF that happens to live in the pharmcat folder; 29 of its 156 variants get ClinVar annotations. Happy to switch if you know a more generic human VCF with ClinVar-relevant variants.

Comment added by Claude Opus 5.5

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ok lets keep tha one then

- conda-forge::python=3.12.15
- pip:
- onkopus==0.7.0
- onkopus==0.7.0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Did you open an issue over at their github to supply the tool as conda package? :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

They have an institutional GitLab, so can't post an Issue, and can't Register.
https://gitlab.gwdg.de/MedBioinf/mtb/onkopus/onkopus

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ok let me send the author an email (she works at my institute now haha)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I asked whether it would be ok for them if we just create the conda package, thats really easy when a pip package is available. I can take care of that. Lets wait for her response :)

echo "${args}"

echo "" | gzip > "${prefix}.ann.vcf.gz"
echo "" | bgzip > "${prefix}.ann.vcf.gz"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For stub its not really important in my eyes but we can do it like this :)

@famosab

famosab commented Oct 20, 2026

Copy link
Copy Markdown
Member

Not yet: Onkopus is hosted on the GWDG GitLab (https://gitlab.gwdg.de/MedBioinf/mtb/onkopus/onkopus). The full list of limitations is in the PR description, ready to forward to the authors if you have a contact there.

I know someone who worked on onkopus but I think they would still prefer to have an issue opened.

@vagkaratzas
vagkaratzas requested a review from famosab October 20, 2026 17:24

@vagkaratzas vagkaratzas left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

  • Versions: htslib and python need their own versions_* emits.
  • Real test: snapshot sanitizeOutput(process.out) instead of hand-picking channels.
  • The PR description is out of date with the code: it mentions gzip (code uses bgzip from htslib), a one-variant BRAF V600E VCF built inside the test (test uses the pharmcat chr22 VCF), a ClinVar-field check instead of a checksum (test snapshots variantsMD5), and the old python_pip_onkopus container. Please refresh it.

Diff 8.81/10 · Overall 8.81/10
nf-core-reviewer 0.1.0 / vagkaratzas-review (rubric v1) · claude-opus-5-5

Comment thread modules/nf-core/onkopus/run/main.nf
Comment thread modules/nf-core/onkopus/run/tests/main.nf.test
vagkaratzas and others added 2 commits October 20, 2026 20:29
Generated by Claude Opus 5.5

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

new module: onkopus

2 participants