CN: per-probe heterozygous BAF spread from the batch reference; --mosaic-prior/--switch-distance; Pi memory guard
scripts/pi_run.sh runs heavy jobs in their own process group and stops them when MemAvailable drops below a floor (Raspberry Pi OS boots with cgroup_disable=memory, so a systemd MemoryMax cap is not available); a 360-sample genotype run with cohort QC had exhausted memory and the OOM killer took down the desktop session. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01814GKVzZVL3FuF3DeiZXhv
This commit is contained in:
1 parent
07a4caff51
commit
46be8f7ffd
5 files changed
+80
-16
No files matched your search
@@ -46,6 +46,7 @@ class CytoModel:
|
||||
ref_lrr_f: npt.NDArray[np.float32] | None = None # same, X/Y from female reference samples
|
||||
ref_lrr_m: npt.NDArray[np.float32] | None = None # same, X/Y from male reference samples
|
||||
ref_het: npt.NDArray[np.float32] | None = None # per-probe median heterozygous BAF
|
||||
ref_het_sd: npt.NDArray[np.float32] | None = None # per-probe robust SD of heterozygous BAF
|
||||
|
||||
|
||||
def run_build_model(
|
||||
@@ -119,8 +120,10 @@ def run_build_model(
|
||||
ref_by_sex[sex] = col
|
||||
n_f, n_m = sexes.count("F"), sexes.count("M")
|
||||
rep.info(f"batch reference sexes: {n_f} F, {n_m} M, {len(sexes) - n_f - n_m} U")
|
||||
from simurg.cn.model import reference_het_spread
|
||||
|
||||
ref_cols = {"ref_lrr": ref_lrr, "ref_lrr_f": ref_by_sex["F"], "ref_lrr_m": ref_by_sex["M"],
|
||||
"ref_het_baf": ref_het, "ref_n_het": n_het} # fmt: skip
|
||||
"ref_het_baf": ref_het, "ref_het_sd": reference_het_spread(baf), "ref_n_het": n_het} # fmt: skip
|
||||
n_ref = len(paths)
|
||||
rep.info(f"batch reference from {n_ref} GTC(s)")
|
||||
header = {
|
||||
@@ -173,7 +176,8 @@ def read_model(path: Path, manifest: Manifest) -> CytoModel:
|
||||
pfb = col("pfb")
|
||||
assert pfb is not None
|
||||
return CytoModel(header, table.column("name").to_pylist(), gc.astype(np.float32), pfb, ref_lrr=col("ref_lrr"),
|
||||
ref_lrr_f=col("ref_lrr_f"), ref_lrr_m=col("ref_lrr_m"), ref_het=col("ref_het_baf")) # fmt: skip
|
||||
ref_lrr_f=col("ref_lrr_f"), ref_lrr_m=col("ref_lrr_m"), ref_het=col("ref_het_baf"),
|
||||
ref_het_sd=col("ref_het_sd")) # fmt: skip
|
||||
|
||||
|
||||
# ================================================================================================ cn call
|
||||
@@ -202,6 +206,8 @@ class CnCallOptions:
|
||||
svlen_mode: str = "signed"
|
||||
mask_bed: Path | None = None
|
||||
bgzip: bool = True
|
||||
mosaic_prior: float = 0.004 # [OURS] tuning knobs (hmm.MOSAIC_PRIOR, hmm.SWITCH_D)
|
||||
switch_d: float = 5e8
|
||||
threads: int = 0
|
||||
force: bool = False
|
||||
argv: list[str] = field(default_factory=list)
|
||||
@@ -340,7 +346,7 @@ def call_sample(si: SampleInput, ctx: dict[str, Any], opts: CnCallOptions) -> di
|
||||
seg_sd = _robust_sd(lrr[auto], 0.05)
|
||||
b_het = baf[auto & (baf > 0.3) & (baf < 0.7)]
|
||||
baf_sd = _robust_sd(b_het, 0.02)
|
||||
dip, hap = hmm.diploid_states(), hmm.haploid_states()
|
||||
dip, hap = hmm.diploid_states(opts.mosaic_prior), hmm.haploid_states(opts.mosaic_prior)
|
||||
counts: dict[str, int] = {}
|
||||
events: list[Any] = []
|
||||
segments: list[dict[str, Any]] = []
|
||||
@@ -378,9 +384,10 @@ def call_sample(si: SampleInput, ctx: dict[str, Any], opts: CnCallOptions) -> di
|
||||
offset = float(np.nanmedian(x_raw)) if haploid else 0.0
|
||||
if not math.isfinite(offset):
|
||||
offset = 0.0
|
||||
prm = hmm.Params(seg_sd, baf_sd, lrr_offset=offset)
|
||||
e = hmm.emissions(states, x_seg, np.full(len(b), np.nan) if haploid else b, pfb[idx], prm)
|
||||
sw = hmm.switch_probs(p)
|
||||
prm = hmm.Params(seg_sd, baf_sd, lrr_offset=offset, switch_d=opts.switch_d)
|
||||
het_sd = model.ref_het_sd[idx].astype(np.float64) if model.ref_het_sd is not None else None
|
||||
e = hmm.emissions(states, x_seg, np.full(len(b), np.nan) if haploid else b, pfb[idx], prm, het_sd)
|
||||
sw = hmm.switch_probs(p, opts.switch_d)
|
||||
path = hmm.viterbi(e, sw, prior)
|
||||
post = hmm.forward_backward(e, sw, prior)
|
||||
evs = extract(chrom, path, states, p)
|
||||
|
||||
Reference in new issue
Block a user