Feature stats dev - #1
Merged
Merged
Conversation
Extend AnnotationQC with two QC metric families beyond BUSCO completeness: - Structural/nesting/length/UTR stats via AGAT agat_sp_statistics.pl --yaml, parsed into a tidy long table results/qc/annotation_stats.tsv (rules/agat_stats.smk, scripts/parse_agat_stats.py, envs/pyutils.yml). - Coding integrity via psauron: annotation-level score (% of CDS scored as real protein) plus the saved per-transcript scoring CSV; CDS extracted with gffread -x as a separate rule so it does not re-trigger compleasm (rules/psauron.smk, scripts/parse_psauron.py, envs/psauron.yml). Hardening for portability: every python-invoking rule runs with PYTHONNOUSERSITE=1 and AGAT with 'env -u PERL5LIB', keeping the conda envs hermetic against leaked ~/.local / ~/apps/perl packages. rule all now targets all three QC tables; profiles/slurm gains resources for the new rules; .gitignore excludes AGAT's runtime log dirs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add config-driven GPU support for the psauron rule: - config.yaml: psauron_use_gpu (default false), psauron_gpu_partition, psauron_gpus - psauron.smk: conditional rule -- the GPU branch uses envs/psauron_gpu.yml (CUDA torch), submits to the configured GPU partition via Snakemake's 'gpu' resource (--gpus=N), and lets psauron auto-detect the GPU (no -c); the CPU branch is unchanged. - envs/psauron_gpu.yml: CUDA pytorch build (numpy<2, scipy<1.15, setuptools<81); documents exporting CONDA_OVERRIDE_CUDA to build on a CPU submit node. - profiles/slurm: psauron resources now live on the rule (they are conditional), so removed from the profile. - README: GPU usage section. CPU-only users leave psauron_use_gpu: false and never build the CUDA env. Verified on Cannon: a GPU run scored the bullfrog draft's CDS on a gpu-partition node (holygpu8a22502) in <3 min (psauron score 92.9%). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every annotation is validated before any metric runs; the workflow halts
loudly on failure (no misleading numbers), and the metrics run on the ORIGINAL
annotation gated by a pass-marker -- nothing is rewritten (AGAT's standardizer
silently drops edge-case features, so it is not used to produce the file the
metrics consume).
Gate (workflow/rules/validate.smk):
- gff_syntax_check: gt gff3validator (genometools) for strict GFF3 syntax.
- gff_validate (scripts/validate_gff.py): custom checks vs the genome -- every
seqid present in the genome FASTA; feature coords within 1..sequence_length;
CDS phase valid (0/1/2); required feature types (CDS/exon/mRNA) present.
Writes a per-annotation report + a validation_summary.tsv row; exits non-zero
with a documented explanation on any failure.
- Optional non-fatal AGAT advisory (config agat_advisory, default off).
Also:
- metric rules (extract_sequences, extract_cds, agat_statistics) now depend on
the {aid}.validated pass-marker and run on the original annotation.
- fail-loud guards: extraction fails on empty output; busco/psauron parsers
fail on N=0 / no rows.
- wildcard_constraints on {aid} to avoid output-pattern ambiguity.
- new envs: genometools; pyfaidx added to pyutils.
Verified on Cannon: raw bullfrog + mouse both pass gt and all custom checks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the 'Input validation' section (gt gff3validator + custom genome checks, fail-loud, metrics run on the original), the agat_advisory config option, and validation_summary.tsv to the outputs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ation
Modeled on the scRNAseq-preprocessing repo: a fast, hermetic default suite plus
opt-in heavy checks, wired into GitHub Actions.
Workflow:
- workflow/rules/common.smk: validate_config() + validate_annotations() run at
load time, raising a clear ValueError on a malformed config/samplesheet.
- channel_priority: strict added to all workflow/envs/*.yml.
Tests (tests/, pytest):
- Fast (always-on, hermetic): snakemake --lint parses; -np dry-run builds the
DAG with all rules + the four QC targets; config & sample-sheet validation
reject malformed inputs; static env checks (channels / channel_priority /
non-empty deps, and every conda: reference resolves) + container declarations
must be docker:// and pinned.
- Opt-in (conftest flags): --run-conda-validation (solve each env + smoke-check
its key tool), --run-container-validation (pull declared images; none yet),
--run-workflow (end-to-end on the local mouse chr1 subset).
- Tiny committed dataset tests/testdata/tiny.{fa,gff3}; the chr1 E2E input is
local-only (gitignored, too big to commit).
CI: .github/workflows/tests.yml (fast suite on push/PR; conda-validation matrix
on manual dispatch). environment.yml runner env. tests/README.md.
Verified on Cannon: fast suite 15 passed / 3 skipped; gffread conda-validation passes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
All rule outputs now live under RESULTS = config.get("results_dir", "results")
instead of a hardcoded results/ prefix. Backward-compatible (default unchanged),
so a test run can redirect outputs to its own dir without clobbering a real
results/ tree — needed for the golden-output E2E test.
Verified: fast suite 15 passed / 3 skipped (default path unchanged); a
results_dir override redirects every output as expected.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The opt-in end-to-end test now runs the pipeline on the chr1 subset into an isolated results_dir and compares all four QC tables against committed golden references, instead of only checking they are non-empty. - tests/reference_outputs/*.tsv: golden QC tables generated from the mouse chr1 subset (eukaryota lineage, CPU psauron). - tests/_helpers.py: assert_table_matches_golden() -- order-independent row match; exact for deterministic columns, per-column tolerance for the model-derived psauron score (+/-2.0) and protein-CDS count (+/-50). - tests/test_workflow_run.py: E2E compares vs golden (isolated results_dir, never touches a real results/); plus always-on test_golden_outputs_wellformed guard. - tests/update_golden.py: regenerate the golden references after an intended change. - tests/README.md + .gitignore updated (ignore the golden-run scratch dir). Verified: fast suite 16 passed / 3 skipped; golden run rc=0 (psauron 98.7%, 6133 CDS; BUSCO deterministic on the chr1 subset). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
agat_sp_statistics.pl emits some symmetric metrics (e.g. the count named "Number A..B overlapping") with a run-to-run-variable A..B direction, because Perl randomizes hash-key iteration order per process. That made annotation_stats.tsv non-reproducible and broke the golden-output E2E comparison. Pin it with PERL_HASH_SEED=0 + PERL_PERTURB_KEYS=0 in the agat_statistics rule (also makes real QC runs reproducible). Verified: two runs now produce byte-identical annotation_stats, matching the committed golden. Widened the golden-run scratch gitignore glob. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A stray trailing tab in annotations.tsv gave the row one more field than the header, so pandas read the extra empty field as an index column and shifted every value one column left: annotation_id became the annotation path and genome_path became nan. validate_annotations() already caught the resulting empty genome_path, but the message named the symptom rather than the cause. Read the sheet with index_col=False so the shift cannot happen, and point at the extra field in the empty-value message for any other way a row goes long. Adds a regression test (verified to fail without index_col=False). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
added sundry feature-level stats and tests