File size: 4,419 Bytes
31d1d63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/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()