Evaluating the annotation-omission model (2026-07-25)
All runs: ONT cDNA, 2M simulated reads (cdna_s1_reads_shuffled.2M.fastq), genome read
mode (spliced genome alignment → bramble projection), --filter-group no-filters,
16 threads, GRCh38.p14 + GCF.pc_lncrna.matched.gtf.
Holdout GTFs follow TranSigner: transcripts are deleted from the set reads were actually simulated from, not from the catalogue at large (deleting unexpressed transcripts orphans no reads and measures nothing).
Caveat on cross-table comparison. Each table computes metrics over the set of transcripts common to the arms in that table. The three-arm table intersects with the transcriptome-mode quant, so its transcript set — and therefore its absolute CCC — differs from the deep-sweep table. Compare within a table, not across tables.
1. The original evidence was diluted, not absent
Global CCC over ~20k transcripts, when the model touches ~50 loci, makes a 4th-decimal delta arithmetically inevitable. Restricting to transcripts that are members of a flagged locus:
| design | n txps | mean |log2 err| full → omission | change |
|---|---|---|---|
| dominant25 | 143 | 1.1203 → 1.0064 | −10.2% |
| origin25 | 131 | 1.0982 → 0.9585 | −12.7% |
| origin50 | 179 | 1.2255 → 1.0512 | −14.2% |
| minor25 | 30 | 0.5993 → 0.6931 | +15.7% (worse) |
| minor50 | 29 | 0.6158 → 0.7561 | +22.8% (worse) |
| locus25 | 17 | 0.3965 → 0.5632 | +42.0% (worse) |
locus* deletes every isoform of a gene, so no survivor exists to correct — flagging
there is harmful by construction. minor* (keep only the dominant isoform) also
regresses, on small n. These are real limitations, not noise to be explained away.
An intermediate restriction — all surviving transcripts at affected genes — is still ~10× too coarse (4,770 affected genes vs 409 acted-on loci) and shows almost nothing:
| design | group | n | mean |log2| full → omission |
|---|---|---|---|
| origin50 | surviving @ affected genes | 6,347 | 0.9391 → 0.9348 |
| origin50 | surviving @ unaffected genes | 5,558 | 0.5735 → 0.5703 |
2. The mechanism is the claimed one (over-attribution)
Signed error at acted-on loci; positive = over-attributed.
| design | median log2(est/truth) | % inflated >2× |
|---|---|---|
| dominant25 | +0.0942 → +0.1249 | 28.0% → 28.7% |
| origin25 | +0.2023 → +0.1910 | 31.3% → 26.0% |
| origin50 | +0.4329 → +0.2909 | 39.1% → 33.0% |
3. Dose-response holds to extreme incompleteness
New holdouts at 75% and 90%. Global CCC, and error reduction on acted-on loci.
| design | orphaned mass | CCC full | CCC omission | delta | flagged loci | acted-on error reduction |
|---|---|---|---|---|---|---|
| dominant50 | 21.5% | 0.85642 | 0.85722 | +0.00080 | 70 | −13.6% (n=196) |
| dominant75 | 31.2% | 0.84173 | 0.84309 | +0.00136 | 98 | −17.4% (n=270) |
| dominant90 | 40.0% | 0.83083 | 0.83243 | +0.00160 | 112 | −17.2% (n=311) |
| origin75 | 76.0% | 0.83310 | 0.83515 | +0.00205 | 78 | −16.2% (n=104) |
| origin90 | 87.6% | 0.78673 | 0.78925 | +0.00252 | 53 | −19.0% (n=37) |
Monotone in incompleteness — the effect roughly triples from 21.5% to 87.6% orphaned.
4. Detection is the stronger claim: high precision, very low recall
Treating "is this locus incomplete?" as classification against holdout truth. A locus is a true positive if any member transcript's gene lost an expressed isoform.
origin50 (7,969 genes lost ≥1 expressed isoform):
| min flagged reads | loci | precision | genes found | recall |
|---|---|---|---|---|
| 1 | 161 | 0.913 | 155 | 0.0195 |
| 2 | 104 | 0.971 | 110 | 0.0138 |
| 3 | 89 | 1.000 | 98 | 0.0123 |
| 5 | 75 | 1.000 | 82 | 0.0103 |
| 10 | 55 | 1.000 | 60 | 0.0075 |
| 50 | 27 | 1.000 | 31 | 0.0039 |
origin25 (4,770 affected): precision 0.787 → 1.000 over the same sweep, recall 0.0180 → 0.0031. dominant25 (1,413 affected): precision 0.522 → 0.944, recall 0.0354 → 0.0127.
Recall saturates at 2–3.5% even at the most permissive threshold: signal-limited, not threshold-limited.
Recall is not limited by the annotation
Is the deleted transcript's junction set a subset of some surviving sibling's (hence undetectable in principle)?
| design | lost txps | single-exon | juncs ⊆ survivor | detectable ceiling |
|---|---|---|---|---|
| origin25 | 5,952 | 78 | 283 | 93.9% |
| dominant25 | 1,413 | 2 | 104 | 92.5% |
| origin50 | 11,904 | 206 | 349 | 95.3% |
93–95% are distinguishable in principle; we recover 2–4%.
5. Where the reads actually go
Junction-evidence accounting from the projection stage:
| annotation | reads projected | junction-informative | disagree with every candidate |
|---|---|---|---|
| full | 1,356,492 | 900,174 (66.4%) | 7,876 (0.87%) |
| origin25 | 1,160,521 | 750,580 (64.7%) | 13,135 (1.75%) |
| origin50 | 871,411 | 525,168 (60.3%) | 16,350 (3.11%) |
Reads vanishing from projection entirely vs the full annotation: 195,971 (origin25), 485,081 (origin50). The junction-mismatch channel the model consumes grows by only 5,259 and 8,474 over its full-annotation floor — 37× and 57× smaller.
The 0.87% all-mismatch rate under the correct annotation is the false-positive floor (alignment/projection error). Signal rises to 1.75%/3.11% — only a 2–3.5× enrichment, which caps how aggressive the novel state can safely be.
6. Three-arm comparison
| design | arm | CCC | MARD | reads assigned |
|---|---|---|---|---|
| origin25 | transcriptome (no compatibility filter) | 0.86916 | 0.3217 | 1,214,436 |
| genome: filter only | 0.87772 | 0.3090 | 1,142,652 | |
| genome: filter + model | 0.87818 | 0.3087 | 1,140,903 | |
| origin50 | transcriptome | 0.83729 | 0.3640 | 957,195 |
| genome: filter only | 0.86512 | 0.3289 | 833,605 | |
| genome: filter + model | 0.86630 | 0.3282 | 830,166 | |
| origin90 | transcriptome | 0.76788 | 0.4273 | 351,302 |
| genome: filter only | 0.82558 | 0.3661 | 282,305 | |
| genome: filter + model | 0.82764 | 0.3648 | 281,285 |
Genome-vs-transcriptome gap: +0.00856 / +0.02783 / +0.05770. Confounded — the arms differ in aligner (direct transcriptome mapping vs spliced genome alignment + projection), not only in filtering. Sections 7–8 remove that confound.
7. The similarity threshold is inert (negative result)
Exposed similarity_threshold on bramble's ProjectionConfig and as oarfish's hidden
--projection-similarity-threshold. Sweeping it on origin25:
| threshold | CCC | reads assigned |
|---|---|---|
| 0.60 (long-read default) | 0.878672 | 1,142,806 |
| 0.30 | 0.878285 | 1,142,838 |
| 0.05 | 0.878073 | 1,142,847 |
A 12× reduction admits 41 more reads out of 1.14M (0.004%) and moves CCC by −0.0006.
The similarity threshold accounts for essentially none of oarfish's robustness to annotation incompleteness. Reads orphaned by a deleted isoform do not produce low-similarity candidates that get filtered — they produce no viable exon-chain match at all, so structural matching rejects them before similarity is ever evaluated.
8. The junction tolerances are the real filter
Exposed max_clip, max_junc_ins, max_junc_gap, max_error_exon. Sweeping the
junction triple (max_clip left at its default so the intervention targets splice
disagreement specifically):
| design | tolerance | reads | CCC | MARD | vs default |
|---|---|---|---|---|---|
| origin25 | 40/40/35 (default) | 1,142,806 | 0.87867 | 0.3080 | — |
| 120/120/120 | 1,155,507 | 0.87557 | 0.3118 | +12,701 reads, CCC −0.00311 | |
| 255/255/255 | 1,160,352 | 0.87341 | 0.3136 | +17,546 reads, CCC −0.00527 | |
| origin50 | 40/40/35 | 833,792 | 0.86543 | 0.3288 | — |
| 120/120/120 | 853,473 | 0.85889 | 0.3368 | +19,681 reads, CCC −0.00654 | |
| 255/255/255 | 864,613 | 0.85403 | 0.3419 | +30,821 reads, CCC −0.01140 | |
| origin90 | 40/40/35 | 282,305 | 0.82558 | 0.3661 | — |
| 120/120/120 | 303,290 | 0.80941 | 0.3875 | +20,984 reads, CCC −0.01617 | |
| 255/255/255 | 309,105 | 0.80402 | 0.3961 | +26,800 reads, CCC −0.02157 |
9. Final decomposition
| mechanism | origin25 | origin50 | origin90 |
|---|---|---|---|
| junction tolerance (40/40/35) | +0.00527 | +0.01140 | +0.02157 |
| annotation-omission novel state | +0.00046 | +0.00118 | +0.00206 |
| similarity threshold (0.60) | ~0 (41 reads) | — | — |
The tolerance filter beats the novel-state model by a consistent ~10:1 at every level of incompleteness, and both grow monotonically with it.
Most exclusion is unbridgeable, not tunable. At maximal permissiveness (255, the
u8 ceiling) only 17.5k–30.8k extra reads are admitted, against ~196k (origin25) and
~485k (origin50) reads lost relative to the full annotation. So >90% of orphaned reads
have no viable exon chain in any surviving transcript — skipped exons are kb-scale
while tolerances cap at 255 nt. That dominant term is structural, not a filter setting.
The tolerance filter explains 62% / 41% / 37% of the genome-vs-transcriptome gap in §6; the remainder is the aligner/mode difference plus that structural term. Note also that relaxing tolerance can change which transcript wins for reads that already projected, so this is not purely an "admit extra reads" experiment — but it is same-aligner, same-mode, which was the confound it was designed to remove.
What this means for the paper
The honest headline is not "the novel state improves accuracy" — that is a 4th-decimal global effect on top of an already-robust baseline. It is:
- Genome-projection mode is intrinsically robust to annotation incompleteness, because structurally incompatible reads are excluded rather than misattributed. Holding CCC 0.826 with 87.6% of library mass orphaned is a strong result by itself.
- The annotation-omission model contributes reporting — near-perfect precision on which loci are incomplete, a capability no competing tool offers — plus a 10–19% error reduction on the loci it acts on.
Recall (2–4%) is the honest weak point and should be stated as such.
Code state
- bramble
ProjectionConfiggainedsimilarity_threshold,max_clip,max_junc_ins,max_junc_gap,max_error_exon(allOption,None= existing presets); passed through at the singleReadEvaluatorconstruction site insrc/api.rs. - oarfish gained five matching hidden
--projection-*flags. - Control: the default path is unchanged to last-ULP. The byte-identity gate did not pass as written — 160 of 65,268 entries differ — but max absolute difference is 1.8e-12 on values of order 10⁶, with column sums exactly equal. That is accumulation-order nondeterminism in the 16-thread run; a read being admitted or excluded moves mass by O(1), not 10⁻¹².
- All uncommitted. The bramble path dependency in
oarfish/Cargo.tomlremains the outstanding release blocker.
Deferred
Tag loci with non-trivial unprojectable reads → local transcript discovery/assembly → re-quantify overlapping annotated and novel transcripts. Recorded separately; deserves its own push.