feat: per-sample reference support via manifest ref/ref_name columns - #71
feat: per-sample reference support via manifest ref/ref_name columns#71mrvollger wants to merge 4 commits into
Conversation
The manifest can now carry ref and ref_name columns so each sample can use its own reference; the two-column manifest with config-level values keeps working, and a '.' cell falls back to the config value. Chromosome names and lengths come only from each sample's BAM header, in header order (the sort order of the data), and a generated per-sample genome file replaces the fai for all bedtools and bigtools sizes arguments (with a parse-time staleness guard, so a leftover genome file can never disagree with its bam header). All reference and chromosome lookups are functions of the sm wildcard. Includes the fixes from the multi-agent code review (manifest cells parsed as literal text, config-specific errors for null ref values, sample-attributed test assertions). Supersedes #44. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…enome file Every multi-chromosome bedtools sort now uses -g with the per-sample genome file (exclude_from_shuffle, clustering_vs_null, wide and one-percent peaks, hap-differences track), and the two sorted intersects in fires_in_peaks that ran without -g are anchored too — an unanchored -sorted sweep only worked while both inputs happened to share an order. exclude_from_shuffle also drops exclude-file contigs that are absent from the sample's bam header, since bedtools sort -g rejects undeclared chromosomes and those records were dead weight. Per-chromosome rules keep plain position sorts; chromosome order cannot apply within one chromosome. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
verify-multi now asserts full content equality between the test and test-rev samples (same reads, reversed header) for peaks and pileup — the one check that catches a silent ordering regression. The manifest reader uses index_col=False with ParserWarning promoted to an error, so a uniformly extra column fails loudly instead of column-shifting or silently dropping a field; the malformed-row check covers NaN and empty cells. config/README.md documents that outputs follow bam header order (not the lexicographic order of earlier FIRE versions) and that old results directories must be rerun from scratch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Second multi-agent review (ordering-focused, with empirical bedtools/bigtools/tabix experiments using chromosome names where header and lexicographic order disagree): no ordering-correctness bugs found. Decisive check: Three confirmed findings, fixed in the latest commit: (1) Migration notes (for the release)
|
The content-equality guard checks file existence up front, so missing files fail loudly instead of comparing two empty streams. The manifest parse error gains a plain-language hint, the README notes that manifest paths cannot contain spaces or quotes (the whitespace-separated format cannot express them), and the err-nan-cell fixture description matches the validator that actually fires. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
sample,bam,ref,ref_name. Each sample can use its own reference genome.refandref_namefor all samples. A.cell in the new columns falls back to the config value for that row. Filled manifest cells override config values (with an INFO line)..fai. A BAM whose contigs are a subset of its fasta now works instead of producing silently empty per-chromosome output.genome_filerule writes a per-sample chrom.sizes file from the BAM header; all bedtools/bigtools sizes arguments use it. The fasta/fai remain only as true references (CRAM encoding, mosdepth).{sm}wildcard (get_ref(wc),get_ref_name(wc),get_chroms(wc),get_excludes(wc)), backed by anlru_cached pysam header reader. Manifest validation runs at parse time withFIRE:-prefixed errors (duplicate samples, pairing rules, malformed rows, missing ref/fai/bam).ref_nameinto itsgenomes.txt; the hg38/GRCh38 auto-excludes are keyed per sample.Supersedes #44.
Behavior change
Because chromosome lists are needed to build the DAG, every snakemake invocation (including dry-runs) now opens all manifest BAMs. Previously a completed run tolerated archived input BAMs. This mirrors the existing parse-time ref/fai checks and is documented in
config/README.md.Testing
pixi run test-dry(new, runs first in CI): 21-check dry-run matrix — back-compat, 4-column, sentinel, override-INFO, levio parse coverage, and one error fixture per validator branch, plus rendered-shell assertions covering both excludes branches.pixi run test+pixi run test-verify(new in CI): the single-sample regression completes 49/49 rules with golden counts identical to main (1,181-line peaks file, 46,223 fire elements) — the chromosome-source swap is behaviorally invisible.pixi run test-multi(new, local): full three-sample run (136/136 rules) with per-samplegenomes.txt(hg38/testref/testref2via sentinel), the empty-excludes branch, and a generated chr20-only BAM proving per-sample chromosome sets.Notes for review
pixi run fmtreformatted shell blocks across the workflow — mechanical whitespace noise beyond the functional changes. Two pre-existing((cat $(...)subshells infire-peaks.smkwere disambiguated to( (cat ...(shfmt correctly rejects the former as arithmetic).rule firestopped producing a bam, and a single globalchain:cannot coexist with per-sample references.test-verify's numbers may need hardening from this PR's first CI run.