File size: 6,209 Bytes
141bacd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""melanocyte deep dive on aldrich: within-melanocyte cKO vs WT DE and pathway scoring."""
from __future__ import annotations
from pathlib import Path
import warnings
warnings.filterwarnings("ignore")

import numpy as np
import pandas as pd
import anndata as ad
import scanpy as sc
from scipy.stats import mannwhitneyu

import os as _os
from pathlib import Path as _Path
PANDA_ROOT = _Path(_os.environ.get("PANDA_ROOT", str(_Path(__file__).resolve().parents[2])))
TARGET = Path(str(PANDA_ROOT / "data/processed/skin/adata_processed.h5ad"))
PROJ   = Path(str(PANDA_ROOT / "discovery/pan_skin/marker/50_aldrich_projections.h5ad"))
OUT    = Path(str(PANDA_ROOT / "discovery/pan_skin/marker"))

PATHWAYS = {
    "MITF_regulon":       ["Mitf", "Dct", "Tyr", "Pmel", "Mlana", "Tyrp1", "Slc24a5",
                           "Slc45a2", "Silv", "Sox10", "Pax3", "Kit", "Ednrb"],
    "Wnt_signaling":      ["Wnt3", "Wnt5a", "Wnt7a", "Wnt10b", "Ctnnb1", "Lef1", "Tcf4",
                           "Tcf7", "Axin2", "Dkk1", "Sfrp1", "Fzd7", "Lrp5", "Lrp6"],
    "BMP_TGF_signaling":  ["Bmp2", "Bmp4", "Bmp5", "Bmp7", "Bmpr1a", "Bmpr1b", "Bmpr2",
                           "Smad1", "Smad3", "Smad5", "Tgfb1", "Tgfb2", "Tgfbr1",
                           "Tgfbr2", "Id1", "Id2", "Id3"],
    "FGF_signaling":      ["Fgf1", "Fgf2", "Fgf7", "Fgf9", "Fgf10", "Fgf20", "Fgfr1",
                           "Fgfr2", "Fgfr3", "Fgfr4", "Etv1", "Etv4", "Etv5", "Spry2",
                           "Spry4", "Dusp6"],
    "Notch_signaling":    ["Notch1", "Notch2", "Notch3", "Jag1", "Jag2", "Dll1", "Dll3",
                           "Dll4", "Hes1", "Hes5", "Hey1", "Hey2", "Rbpj", "Maml1"],
    "Hedgehog":           ["Shh", "Ihh", "Ptch1", "Ptch2", "Smo", "Gli1", "Gli2", "Gli3",
                           "Hhip", "Sufu"],
    "EMT":                ["Zeb1", "Zeb2", "Snai1", "Snai2", "Twist1", "Twist2", "Vim",
                           "Cdh2", "Fn1", "Mmp2", "Mmp9", "Prrx1"],
    "Cell_cycle":         ["Ccnd1", "Ccnd2", "Ccne1", "Ccna2", "Ccnb1", "Cdk1", "Cdk2",
                           "Cdk4", "Cdk6", "Mki67", "Top2a", "Pcna", "Mcm2", "Mcm3"],
    "Neural_crest":       ["Sox10", "Sox9", "Sox2", "Pax3", "Foxd3", "Nes", "Ngfr",
                           "Ednrb", "Kit", "Tfap2a"],
    "Apoptosis":          ["Bax", "Bak1", "Bad", "Bid", "Bcl2", "Bcl2l1", "Casp3",
                           "Casp9", "Casp8", "Fas", "Fasl", "Trp53", "Cdkn1a"],
}


def pathway_scoring(sub, pathway_dict):
    for name, genes in pathway_dict.items():
        present = [g for g in genes if g in sub.var_names]
        if not present:
            sub.obs[f"{name}"] = 0.0
            continue
        sc.tl.score_genes(sub, gene_list=present, score_name=f"{name}",
                          random_state=0, use_raw=False)
    return sub


def main():
    a = ad.read_h5ad(TARGET)
    p = ad.read_h5ad(PROJ)
    a.obs["pred_label"] = p.obs["pred_bbse_label"].values

    mask = a.obs["pred_label"] == "melanocyte"
    print(f"[mel] melanocyte cells: {int(mask.sum())} "
          f"({int((mask & (a.obs['genotype']=='En1-cKO')).sum())} cKO, "
          f"{int((mask & (a.obs['genotype']=='WT')).sum())} WT)", flush=True)
    if mask.sum() < 30:
        print("[mel] too few melanocyte cells")
        return

    sub = a[mask].copy()
    sub = pathway_scoring(sub, PATHWAYS)

    print("\n[mel] pathway score cKO vs WT (positive = up in cKO):")
    rows = []
    for name in PATHWAYS.keys():
        s = sub.obs[name].astype(float).values
        g = sub.obs["genotype"].values
        c_scores = s[g == "En1-cKO"]
        w_scores = s[g == "WT"]
        stat, pval = mannwhitneyu(c_scores, w_scores, alternative="two-sided")
        delta = c_scores.mean() - w_scores.mean()
        rows.append({"pathway": name, "delta_cKO_minus_WT": round(delta, 4),
                     "MannU_p": pval,
                     "cKO_mean": round(c_scores.mean(), 4),
                     "WT_mean": round(w_scores.mean(), 4)})
        star = "***" if pval < 0.001 else "**" if pval < 0.01 else "*" if pval < 0.05 else ""
        print(f"  {name:20s} delta={delta:+.4f} p={pval:.2e} {star}")

    pd.DataFrame(rows).sort_values("MannU_p").to_csv(OUT / "56_melanocyte_pathways.csv", index=False)

    print("\n[mel] within-melanocyte cKO vs WT DE:")
    sc.tl.rank_genes_groups(sub, "genotype", method="wilcoxon", n_genes=50, use_raw=False)
    de = pd.DataFrame({
        "cKO_up_gene": sub.uns["rank_genes_groups"]["names"]["En1-cKO"][:20],
        "cKO_up_lfc":  sub.uns["rank_genes_groups"]["logfoldchanges"]["En1-cKO"][:20],
        "WT_up_gene":  sub.uns["rank_genes_groups"]["names"]["WT"][:20],
        "WT_up_lfc":   sub.uns["rank_genes_groups"]["logfoldchanges"]["WT"][:20],
    })
    print(de.to_string(index=False))
    de.to_csv(OUT / "56_melanocyte_wilcoxon_cko_vs_wt.csv", index=False)

    lines = ["# Melanocyte deep dive — Aldrich En1-cKO vs WT",
             "",
             f"PANDA-MLP-predicted melanocyte cells: **{int(mask.sum())} total** "
             f"({int((mask & (a.obs['genotype']=='En1-cKO')).sum())} cKO, "
             f"{int((mask & (a.obs['genotype']=='WT')).sum())} WT).",
             "",
             "The v3b+v3c cross-model replication showed ~2× melanocyte enrichment in cKO "
             "(log2fc +1.04, Fisher p ≈ 4×10⁻⁶). Here we probe what's happening WITHIN the "
             "melanocyte compartment.",
             "",
             "## Pathway score comparisons (MannU cKO vs WT)",
             ""]
    dfp = pd.DataFrame(rows).sort_values("MannU_p")
    lines.append(dfp.to_markdown(index=False))
    lines += ["",
              "## Within-melanocyte Wilcoxon DE (top 20 each direction)",
              ""]
    de_show = de.copy()
    de_show["cKO_up_lfc"] = de_show["cKO_up_lfc"].round(3)
    de_show["WT_up_lfc"]  = de_show["WT_up_lfc"].round(3)
    lines.append(de_show.to_markdown(index=False))
    (OUT / "56_melanocyte_deep_dive.md").write_text("\n".join(lines))
    print(f"[mel] wrote {OUT}/56_melanocyte_deep_dive.md")


if __name__ == "__main__":
    main()