Repository navigation
feat: Add vcf_annotate_vepyr subworkflow - #13070
Conversation
Compose optional bcftools normalisation with vepyr annotation and add published-fixture tests for indexed, unindexed, bypass and stub paths. Generated by Codex
Add an optional repository input that downloads one shared cache before annotation, retaining the existing local-cache path. Document revision and contig filters. Exercise local-cache bypass, remote stubs and a real two-sample annotation using the published chr22 cache. Generated by Codex
Load ./nextflow.config only in the tests that rely on its ext.args (BCFTOOLS_NORM, HUGGINGFACE_DOWNLOAD), following the nf-core testing spec and the review of nf-core#13071. The no-normalise test runs without it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the UNTAR setup into the three local-cache tests so the Hugging Face and stub tests no longer fetch and extract cache.tar.gz. Mention the optional Hugging Face download in the meta.yml summary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With no ext.prefix and meta.id equal to the input basename, the default output name matches the staged input symlink, so bcftools norm rewrites the source file through it. Add the input/output collision guard used by bcftools/annotate, csq, filter, convert and pluginfilltags, in script and stub, with module and vcf_annotate_vepyr regression tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The input/output collision guard is a module fix, so it now lives in its own PR. Keep the subworkflow regression test, which passes once nf-core#13076 is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test asserts the bcftools/norm guard from nf-core#13076, which is not on master yet, so it fails in CI. Restore the meta.yml wording that matches the current module; both come back once nf-core#13076 is merged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…core#13076 bcftools/norm now defaults to ${meta.id}_norm and refuses colliding prefixes, so drop the ext.prefix workaround from the documented config. Add a test where the sample ID matches the input basename. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jonasscheid
left a comment
There was a problem hiding this comment.
Nice, I suggest using the nf-core/agents AGENTS.md for future PRs
--> The AI disclosure doesn't match nf-core/agents. The commits say "Generated by Codex" plus a Claude co-author, and the PR body ends with a Claude Code footer. nf-core/agents asks for "Generated by {name}" placed above the checklist.
| workflow VCF_ANNOTATE_VEPYR { | ||
| take: | ||
| ch_vcf // channel: [ val(meta), path(vcf), path(tbi) ] (tbi optional, pass []) | ||
| ch_cache // channel: [ val(meta2), path(cache) ] (unused when val_hf_repo is set, pass [[], []]) |
There was a problem hiding this comment.
I think more user friendly would be to throw an error if ch_cach and val_hf_repo are set
There was a problem hiding this comment.
Done in cb18242. The subworkflow now fails with set either ch_cache or val_hf_repo, not both when both are set. For symmetry it also fails with no cache given, set ch_cache or val_hf_repo when neither is set; before, that case surfaced later as an unclear VEPYR_ANNOTATE error. Two new stub tests, cache and Hugging Face repo - fails and no cache - fails, assert workflow.failed and the message.
| all contigs present in the VCF, for example: | ||
|
|
||
| ``` | ||
| withName: 'HUGGINGFACE_DOWNLOAD' { |
There was a problem hiding this comment.
AI-hint:
The Hugging Face path only works if the pipeline also sets ext.args = '--repo-type dataset' on HUGGINGFACE_DOWNLOAD. That flag is required, not optional, and nf-core guidance says required arguments should be inputs, not ext.args.
There was a problem hiding this comment.
Done in cb18242, without a new input. vepyr caches are always HF datasets, so the subworkflow passes datasets/<owner>/<repo> to HUGGINGFACE_DOWNLOAD (a datasets/ prefix already in val_hf_repo is kept). hf download 1.18.0, the version the module pins, resolves that ID without --repo-type; the bare ID is looked up as a model. Nothing required is left in ext.args, only the optional --revision/--include. I've removed --repo-type dataset from the test config and meta.yml. The real two-sample HF test still passes with the same variantsMD5.
| tag "huggingface" | ||
| tag "huggingface/download" | ||
|
|
||
| test("homo_sapiens - vcf - normalise") { |
There was a problem hiding this comment.
optional:
The normalisation branch is never actually tested. (tests L18, tests L75) I checked the test data: input.vcf.gz has 1,000 records and none are multiallelic. Combined with --do-not-normalize, bcftools norm changes nothing.
That is why the normalise and no-normalise snapshots share the same variantsMD5 (fdddbf25…).
That MD5 is computed over full record lines, INFO included, so the annotation itself is covered. Only the split step is untested.
A test VCF with one or two multiallelic sites would fix this.
There was a problem hiding this comment.
Fixed in cb18242. nf-core/test-datasets#2298 adds input_multiallelic.vcf.gz: the same HG002 window before normalisation, 986 records, 14 of them multiallelic. Both normalise tests now read it and assert 1,000 output records, all biallelic. Splitting it reproduces input.vcf.gz exactly, so the snapshots keep variantsMD5 fdddbf25…. That is the same as the no-normalise test, but now it shows split + annotate equals annotating the pre-split input; before, it was a no-op. The two tests need #2298 merged before they pass in CI; locally they pass against its branch.
There was a problem hiding this comment.
Follow-up in 643d2b1: per the suggestion on nf-core/test-datasets#2298, the normalise tests no longer need new test data. A setup step runs BCFTOOLS_NORM (aliased BCFTOOLS_JOIN_MULTIALLELICS) with --multiallelics +both --do-not-normalize on input.vcf.gz. That joins the 1,000 records into 986, 14 of them multiallelic, and the subworkflow splits them again. --do-not-normalize is needed because the module always passes --fasta-ref, and left-aligning fails on the VCF's chr22 vs the FASTA's 22. The task logs confirm 14 records joined in setup and 14 split in the subworkflow. Snapshots are unchanged, and the tests pass against the published test data.
| } | ||
| } | ||
|
|
||
| test("homo_sapiens - vcf - normalise - sample id matches input basename") { |
There was a problem hiding this comment.
The "sample id matches input basename" test checks bcftools/norm behaviour, not subworkflow logic. (tests L231) That module already has its own test for it (from #13076). Dropping it here saves a full vepyr run in CI.
There was a problem hiding this comment.
Removed in cb18242, together with its snapshot.
| script "modules/nf-core/untar/main.nf" | ||
| process { | ||
| """ | ||
| input[0] = Channel.of([ |
There was a problem hiding this comment.
de-capitalize Channel. Wont work anymore with higher nextflow versions. Should be channel
There was a problem hiding this comment.
Done in cb18242. Every Channel. in the tests is now channel..
| @@ -0,0 +1,94 @@ | |||
| # yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json | |||
| name: "vcf_annotate_vepyr" | |||
| description: | | |||
There was a problem hiding this comment.
Docs and prose (nf-core/agents prose rules)
One sentence doesn't parse. (meta.yml L26-29) "The configuration vepyr's Ensembl VEP parity tests are validated on splits multiallelic records…" needs rewording. It also says the index "vepyr needs", but VEPYR_ANNOTATE builds the index itself when it is missing. Writing it in bcftools norm only saves a tabix step.
The ext.prefix paragraph describes module internals. (meta.yml L37-39) Under the rule to scope prose to the immediate task, it can go.
"Pipelines should default it to true" appears three times. Keep one. The three places are:
meta.yml L25, in the description
meta.yml L78, in the val_normalize input
main.nf L16, as a comment
The constraints on ch_fasta and ch_cache aren't documented. (meta.yml L57, meta.yml L62)
Both must be value channels. If a pipeline passes a queue channel, only the first sample gets annotated.
BCFTOOLS_NORM output must be bgzipped VCF. -Ob and -Ou produce BCF, and -Ov produces plain VCF, which makes vepyr fall back to --fork 1.
There was a problem hiding this comment.
All addressed in cb18242:
- Reworded the configuration sentence.
--write-index=tbiis now described as optional: it only saves the tabix step, because VEPYR_ANNOTATE builds a missing index. - Removed the
ext.prefixparagraph. - "Default it to true" now appears once, in the
val_normalizedescription. ch_cacheandch_fastaare documented as value channels (channel.value(...)or.collect()), noting that a queue channel annotates only the first sample.- Documented keeping BCFTOOLS_NORM output as bgzip VCF (
--output-type z): VEPYR_ANNOTATE runs a single pipeline for BCF (-Ob/-Ou) and plain VCF (-Ov).
- Prefix val_hf_repo with datasets/, so HUGGINGFACE_DOWNLOAD needs no required --repo-type in ext.args; only --revision/--include remain. - Fail when both ch_cache and val_hf_repo are set, or neither, and test both failures. - Test normalisation on input_multiallelic.vcf.gz (986 records, 14 multiallelic; nf-core/test-datasets#2298): the output has 1,000 biallelic records and the same variantsMD5 as annotating the pre-split input.vcf.gz without normalisation. - Drop the basename test (covered by the bcftools/norm module tests) and use channel instead of Channel. - meta.yml: reword the bcftools norm configuration, drop the ext.prefix paragraph, keep one "default to true", document that ch_cache and ch_fasta must be value channels and that BCF or plain VCF output makes VEPYR_ANNOTATE run a single pipeline. Generated by Claude Code
|
@jonasscheid I've fixed the disclosure: the PR body now ends with |
Instead of a new test-datasets file (nf-core/test-datasets#2298), the normalise tests join input.vcf.gz back into multiallelic records with an aliased BCFTOOLS_NORM in setup: --multiallelics +both turns 1,000 records into 986, 14 of them multiallelic, and the subworkflow splits them again. --do-not-normalize is needed because the module always passes --fasta-ref, and left-aligning fails on chr22 vs 22. Snapshots are unchanged. Generated by Claude Code
Sync the vcf_annotate_vepyr tests with nf-core/modules#13070 643d2b157: the normalise tests join input.vcf.gz back into multiallelic records with an aliased BCFTOOLS_NORM in setup, so the staged input_multiallelic.vcf.gz (nf-core/test-datasets#2298) is no longer needed. Revert its staging in stage_testdata.py and the harness hash, run the aliased process under amd64 emulation like BCFTOOLS_NORM, and drop the #2298 references from the README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vcf_annotate_vepyr merged as nf-core/modules#13070 (7d5d5ab); the mirror here is byte-identical to it. Install it with `nf-core subworkflows install vcf_annotate_vepyr`, which also installs vepyr/annotate, bcftools/norm and huggingface/download, instead of copying it from this repository. Add an nf-core subworkflow badge next to the module badge and mark the submission steps done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d badge (#167) * nf-core: sync vcf_annotate_vepyr with nf-core/modules#13070 Mirror the subworkflow as it stands after the #13070 review round: optional Hugging Face cache download (val_hf_repo, datasets/ prefix added by the subworkflow), errors when both or neither of ch_cache and val_hf_repo are set, normalization tests on a multiallelic input, and the reworded meta.yml. The dev harness follows: bcftools/norm pinned past #13076 (default ${meta.id}_norm prefix and collision guard), huggingface/download fetched at the same commit and run under amd64 emulation, the parity test passes the new seventh argument, and stage_testdata.py builds input_multiallelic.vcf.gz from raw_chr22.vcf.gz, checked against the md5 published in nf-core/test-datasets#2298. Docs: nextflow.md drops the required ext.prefix, documents the Hugging Face cache and value-channel inputs, and copies both helper modules; the subworkflow diagram gains the download branch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * nf-core: build the multiallelic test input in setup, as upstream Sync the vcf_annotate_vepyr tests with nf-core/modules#13070 643d2b157: the normalise tests join input.vcf.gz back into multiallelic records with an aliased BCFTOOLS_NORM in setup, so the staged input_multiallelic.vcf.gz (nf-core/test-datasets#2298) is no longer needed. Revert its staging in stage_testdata.py and the harness hash, run the aliased process under amd64 emulation like BCFTOOLS_NORM, and drop the #2298 references from the README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: advertise the merged nf-core subworkflow vcf_annotate_vepyr merged as nf-core/modules#13070 (7d5d5ab); the mirror here is byte-identical to it. Install it with `nf-core subworkflows install vcf_annotate_vepyr`, which also installs vepyr/annotate, bcftools/norm and huggingface/download, instead of copying it from this repository. Add an nf-core subworkflow badge next to the module badge and mark the submission steps done. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Adds
vcf_annotate_vepyr, an end-to-end VCF annotation subworkflow built on vepyr, a Rust reimplementation of Ensembl VEP.It composes three existing modules:
huggingface/download, which gained whole-repository downloads in feat: huggingface/download: support whole repository downloads #13071bcftools/normvepyr/annotate, added in Add vepyr/annotate module #13001Steps
val_hf_repois set (e.g.biodatageeks/vepyr_116_GRCh38_ensembl), the vepyr Parquet cache is downloaded from that Hugging Face dataset once and shared across all samples. Otherwise the local cache inch_cacheis used. Setting both, or neither, is an error. An optional revision and chromosome filters are passed throughHUGGINGFACE_DOWNLOAD'sext.args.val_normalize). Runsbcftools norm.meta.ymldocuments the configuration used in vepyr's Ensembl VEP parity tests: split multiallelic records, no indel left-alignment. If no index is written, vepyr builds one.vepyr annotate --everythingemits[ meta, vcf.gz, tbi ].Tests
All tests use the HG002 / Ensembl 116 chr22 fixtures from nf-core/test-datasets#2270:
setupstep builds that input by joininginput.vcf.gzwithbcftools norm --multiallelics +both. The tests assert 1,000 biallelic output records and the same variantsMD5 as annotatinginput.vcf.gzwithout normalisation.ch_cacheandval_hf_repoare setValidation:
--ci: 8/8 pass with--profile=+docker,arm64and with--profile=+conda(osx-arm64).1d4a92b815eb6193e6f4546f4ab35978, across 1,000 records.nf-core subworkflows lintpasses (35 passed, 0 warnings) and the prek hooks pass.Generated by Claude Code
PR checklist
topic: versions(provided by the modules).label(provided by the modules).nf-core subworkflows test vcf_annotate_vepyr --profile dockernf-core subworkflows test vcf_annotate_vepyr --profile singularity(upstream CI)nf-core subworkflows test vcf_annotate_vepyr --profile conda(upstream CI)