CN: MF split normalised by per-probe reference BAF noise; genotype-based complete loss (CYTO-041)
The mosaic BAF split is now estimated over heterozygous calls against each probe's expected noise (the reference heterozygous spread scaled to the sample), inverting the median of |N(+-d, sigma)|. A mosaic loss lacking the heterozygous calls its PFB predicts gets MF 1 and is promoted (CYTO-020). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01814GKVzZVL3FuF3DeiZXhv
This commit is contained in:
1 parent
19bc6ca986
commit
662addf5eb
4 files changed
+90
-31
No files matched your search
@@ -12,7 +12,7 @@ from typer.testing import CliRunner
|
||||
|
||||
from simurg.cli.main import app
|
||||
from simurg.cn import hmm
|
||||
from simurg.cn.events import Event, Thresholds, _mf_from_baf, apply_thresholds, effective_size, extract
|
||||
from simurg.cn.events import Event, Thresholds, _mf_from_baf, apply_thresholds, complete_loss, effective_size, extract
|
||||
from simurg.cn.gcwave import gc_correct
|
||||
from simurg.cn.model import gc_fractions, population_bfreq
|
||||
from simurg.formats.gtc import Gtc, write_gtc
|
||||
@@ -237,12 +237,15 @@ def test_mf_refinements() -> None: # CYTO-018 / CYTO-041
|
||||
b = 0.5 + rng.normal(0, sd, 400)
|
||||
mf = _mf_from_baf("MDEL", b, sd)
|
||||
assert mf is not None and mf < 0.08
|
||||
assert (_mf_from_baf("MDEL", b, 0.0) or 0) > 0.05 # uncorrected, the old estimate was biased upwards
|
||||
assert (_mf_from_baf("MDEL", b) or 0) > 0.05 # uncorrected, the old estimate was biased upwards
|
||||
# a true 40 % mosaic loss is still recovered
|
||||
d = 0.4 / (2 * (2 - 0.4))
|
||||
b = 0.5 + rng.choice([-d, d], 400) + rng.normal(0, sd, 400)
|
||||
assert abs((_mf_from_baf("MDEL", b, sd) or 0) - 0.4) < 0.08
|
||||
# no heterozygotes where ~50 are expected: a complete (constitutional) loss
|
||||
b = rng.choice([0.0, 1.0], 100) + rng.normal(0, 0.01, 100)
|
||||
assert _mf_from_baf("MDEL", np.clip(b, 0, 1), sd, np.full(100, 0.3)) == 1.0
|
||||
assert _mf_from_baf("MDEL", np.clip(b, 0, 1), sd, np.full(100, 0.01)) is None # too few expected
|
||||
# no heterozygous calls where ~12 are expected: a complete (constitutional) loss
|
||||
hom = np.full(30, 1, dtype=np.uint8)
|
||||
assert complete_loss(hom, np.full(30, 0.3))
|
||||
assert not complete_loss(hom, np.full(30, 0.02)) # too few expected
|
||||
mixed = hom.copy()
|
||||
mixed[:8] = 2
|
||||
assert not complete_loss(mixed, np.full(30, 0.3))
|
||||
Reference in new issue
Block a user