CN: noise-corrected BAF split and complete-loss MF (CYTO-041); Pi tuning harness
Mosaic fraction from the BAF split now subtracts the heterozygous BAF noise (median |BAF-0.5| of unsplit hets = 0.6745 sigma_b), and a mosaic loss lacking its expected heterozygotes gets MF 1 and is promoted to a constitutional DEL (CYTO-020). Adds scripts/v2/cn_tune.sh + cn_tune_report.py (GSE165845 rounds on the Pi). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01814GKVzZVL3FuF3DeiZXhv
This commit is contained in:
1 parent
8ab8e632b9
commit
19bc6ca986
6 files changed
+140
-8
No files matched your search
+19
-1
@@ -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, apply_thresholds, effective_size, extract
|
||||
from simurg.cn.events import Event, Thresholds, _mf_from_baf, apply_thresholds, 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
|
||||
@@ -228,3 +228,21 @@ def test_packaged_cn_data() -> None: # the built-in mask and cytobands ship wit
|
||||
m = read_mask(None, build)
|
||||
assert len(m) >= 24 and all(s <= e for iv in m.values() for s, e in iv)
|
||||
assert gzip.decompress(_builtin_file(f"cytoBand_{build}.txt.gz")).startswith(b"chr1\t0\t")
|
||||
|
||||
|
||||
def test_mf_refinements() -> None: # CYTO-018 / CYTO-041
|
||||
rng = np.random.default_rng(3)
|
||||
sd = 0.04
|
||||
# unsplit heterozygotes: noise alone must not look like a mosaic split
|
||||
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
|
||||
# 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
|
||||
Reference in new issue
Block a user