ScooBDoob / paper_figures /data /p53_preference_data.py
ynuozhang
Upload ScooBDoob code without binary caches
31d1d63
Raw History Blame Contribute Delete
4.42 kB
#!/usr/bin/env python
import argparse
import json
import sys
from pathlib import Path
import numpy as np
from scipy.cluster.hierarchy import linkage, leaves_list
from scipy.spatial.distance import squareform
from scipy.stats import spearmanr
ROOT = Path(__file__).resolve().parents[2]
CACHE = ROOT / "data" / "p53" / "fig_data"
sys.path.insert(0, str(ROOT))
SEED = 0
def split_half_all(gamma, n_splits, rng, permute=False):
"""Split-half over ALL receptors: does the ligand-preference structure reproduce?"""
n_lig, n_rec = gamma.shape
iu = np.triu_indices(n_lig, k=1)
out = []
for _ in range(n_splits):
m = gamma.copy()
if permute:
for li in range(n_lig):
m[li] = m[li, rng.permutation(n_rec)]
p = rng.permutation(n_rec)
A, B = p[: n_rec // 2], p[n_rec // 2 :]
r_, _ = spearmanr(np.corrcoef(m[:, A])[iu], np.corrcoef(m[:, B])[iu])
if np.isfinite(r_):
out.append(r_)
return np.array(out)
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--splits", type=int, default=400)
a = ap.parse_args()
from scoobdoob.validation import preference as WS
CACHE.mkdir(parents=True, exist_ok=True)
gamma, ligs, frames, strat = WS.gamma_matrix()
n_lig, n_rec = gamma.shape
labs = np.unique(strat)
C = np.corrcoef(gamma)
D = np.clip(1.0 - C, 0, 2)
np.fill_diagonal(D, 0.0)
lig_order = leaves_list(linkage(squareform(D, checks=False), method="average"))
rec_order = np.concatenate([np.where(strat == l)[0] for l in labs])
tot = gamma.var()
between = np.zeros_like(gamma)
for l in labs:
m_ = strat == l
between[:, m_] = gamma[:, m_].mean(axis=1, keepdims=True)
frac_between = float(between.var() / tot)
frac_within = float((gamma - between).var() / tot)
obs_all = split_half_all(gamma, a.splits, np.random.default_rng(SEED))
nul_all = split_half_all(
gamma, a.splits, np.random.default_rng(SEED + 1), permute=True
)
WS.rng = np.random.default_rng(SEED + 2)
obs_w = WS.split_half_within(gamma, strat, n_splits=a.splits)
rng = np.random.default_rng(SEED + 3)
gperm = gamma.copy()
for l in labs:
m_ = np.where(strat == l)[0]
for li in range(n_lig):
gperm[li, m_] = gperm[li, rng.permutation(m_)]
WS.rng = np.random.default_rng(SEED + 4)
nul_w = WS.split_half_within(gperm, strat, n_splits=a.splits)
p_within = float((nul_w >= obs_w.mean()).mean())
np.savez_compressed(
CACHE / "preference.npz",
gamma=gamma,
strat=strat,
ligands=np.array(ligs),
frames=np.array(frames),
lig_order=lig_order,
rec_order=rec_order,
obs_all=obs_all,
nul_all=nul_all,
obs_within=obs_w,
nul_within=nul_w,
frac_within=np.array(frac_within),
frac_between=np.array(frac_between),
)
stats = {
"n_ligands": int(n_lig),
"n_receptors": int(n_rec),
"n_strata": int(len(labs)),
"stratum_sizes": [int((strat == l).sum()) for l in labs],
"n_splits": int(a.splits),
"seed": SEED,
"gamma_var_total": float(tot),
"frac_within": frac_within,
"frac_between": frac_between,
"splithalf_all_mean": float(obs_all.mean()),
"splithalf_all_sd": float(obs_all.std()),
"splithalf_all_null_mean": float(nul_all.mean()),
"splithalf_within_mean": float(obs_w.mean()),
"splithalf_within_sd": float(obs_w.std()),
"splithalf_within_null_mean": float(nul_w.mean()),
"p_null_ge_observed_within": p_within,
}
(CACHE / "preference.json").write_text(json.dumps(stats, indent=1, default=float))
print(
f" {n_lig} ligands x {n_rec} receptors, {len(labs)} strata "
f"{stats['stratum_sizes']}"
)
print(
f" var(gamma): within {100 * frac_within:.1f}% between {100 * frac_between:.1f}%"
)
print(
f" split-half all receptors : {obs_all.mean():+.4f} +/- {obs_all.std():.4f} "
f"(null {nul_all.mean():+.4f})"
)
print(
f" split-half within stratum: {obs_w.mean():+.4f} +/- {obs_w.std():.4f} "
f"(null {nul_w.mean():+.4f}, p={p_within:.4f})"
)
print(f"-> {CACHE / 'preference.npz'}\n-> {CACHE / 'preference.json'}")
if __name__ == "__main__":
main()