Download experiments/37_miphei_diag.py from Pathstudy/fourmodal-pathology-bind: direct link, hf CLI and curl.
- Browser
- Download file 4.45 kB
-
https://huggingface.co/Pathstudy/fourmodal-pathology-bind/resolve/main/experiments/37_miphei_diag.py
- Command line
-
hf download hf://Pathstudy/fourmodal-pathology-bind/experiments/37_miphei_diag.py
-
curl -L -o 37_miphei_diag.py https://huggingface.co/Pathstudy/fourmodal-pathology-bind/resolve/main/experiments/37_miphei_diag.py
4.45 kB
| """MIPHEI-ViT vs GigaTIME virtual mIF on ORION, against the real mIF of the same tiles (tile means). | |
| MIPHEI was trained on the ORION official train split -> 'clean' = official TEST tiles (2 patients, never seen); | |
| 'seen' = official TRAIN tiles (training data of MIPHEI, optimistic). GigaTIME never saw ORION (clean everywhere). | |
| (a) per-channel Spearman of tile means (pooled and within-slide) | |
| (b) direct real-mean <-> virtual-mean retrieval (rank-gaussianised means, cosine; no learned head), 100-galleries | |
| Output results/miphei_diag.csv, results/miphei_diag_retrieval.csv | |
| """ | |
| import json | |
| import os | |
| import numpy as np | |
| import pandas as pd | |
| from scipy.special import ndtri | |
| from scipy.stats import rankdata, spearmanr | |
| from common import CACHE, ROOT, SPLITS, load_all_tiles | |
| OUT = os.path.join(ROOT, "results") | |
| ORION_CH = ["Hoechst", "CD31", "CD45", "CD68", "CD4", "FOXP3", "CD8a", "CD45RO", "CD20", "PD-L1", "CD3e", | |
| "CD163", "E-cadherin", "PD-1", "Ki67", "Pan-CK", "SMA"] # order of orion_real_if_means.npy (25_) | |
| GT = {"Hoechst": ["DAPI"], "CD68": ["CD68"], "CD4": ["CD4"], "CD8a": ["CD8"], "CD20": ["CD20"], "PD-L1": ["PD-L1"], | |
| "CD3e": ["CD3"], "Ki67": ["Ki67"], "Pan-CK": ["CK"], "SMA": ["Actin-D", "Transgelin"]} | |
| df = load_all_tiles() | |
| slide = df.in_slide_name.values | |
| real = np.load(os.path.join(CACHE, "gigatime", "orion_real_if_means.npy")) | |
| mch = json.load(open(os.path.join(CACHE, "miphei", "channels.json")))["channels"] | |
| mip = np.load(os.path.join(CACHE, "miphei", "orion_means.npy")) | |
| gch = json.load(open(os.path.join(CACHE, "gigatime", "channels.json")))["channels"] | |
| gm = np.load(os.path.join(CACHE, "gigatime", "orion_means.npy")) | |
| off = pd.read_csv(os.path.join(SPLITS, "orion_official", "fold0.csv")).split.values | |
| sets = {"clean (official test)": off == "test", "seen (official train)": off == "train"} | |
| def within(a, b, m): | |
| r, w = [], [] | |
| for s in np.unique(slide[m]): | |
| i = m & (slide == s) | |
| if i.sum() >= 15 and a[i].std() > 0 and b[i].std() > 0: | |
| r.append(spearmanr(a[i], b[i])[0]); w.append(i.sum()) | |
| return float(np.average(r, weights=w)) if r else np.nan | |
| rows = [] | |
| for ch in mch: | |
| r = real[:, ORION_CH.index(ch)] | |
| for sname, m in sets.items(): | |
| row = {"channel": ch, "set": sname, | |
| "MIPHEI pooled": spearmanr(mip[m, mch.index(ch)], r[m])[0], | |
| "MIPHEI within-slide": within(mip[:, mch.index(ch)], r, m)} | |
| if ch in GT: | |
| g = gm[:, [gch.index(x) for x in GT[ch]]].mean(1) | |
| row.update({"GigaTIME pooled": spearmanr(g[m], r[m])[0], "GigaTIME within-slide": within(g, r, m)}) | |
| rows.append(row) | |
| C = pd.DataFrame(rows) | |
| rg = lambda x: ndtri((np.apply_along_axis(rankdata, 0, x) - 0.5) / len(x)) | |
| def g100(a, b, draws=50, seed=0): | |
| a = a / np.linalg.norm(a, axis=1, keepdims=True); b = b / np.linalg.norm(b, axis=1, keepdims=True) | |
| rng = np.random.default_rng(seed); r = [] | |
| for _ in range(draws): | |
| s = rng.choice(len(a), min(100, len(a)), replace=False) | |
| sim = a[s] @ b[s].T; d = np.diag(sim)[:, None] | |
| r.append(((sim > d).sum(1) == 0).mean() / 2 + ((sim.T > d).sum(1) == 0).mean() / 2) | |
| return float(np.mean(r)) | |
| ten = list(GT) | |
| Rt = [] | |
| for sname, m in sets.items(): | |
| R16 = real[m][:, [ORION_CH.index(c) for c in mch]] | |
| R10 = real[m][:, [ORION_CH.index(c) for c in ten]] | |
| G10 = np.stack([gm[m][:, [gch.index(x) for x in GT[c]]].mean(1) for c in ten], 1) | |
| Rt += [{"set": sname, "n": int(m.sum()), "pair": "real <-> MIPHEI (16 ch)", "R@1_g100": g100(rg(R16), rg(mip[m]))}, | |
| {"set": sname, "n": int(m.sum()), "pair": "real <-> MIPHEI (10 shared ch)", "R@1_g100": g100(rg(R10), rg(mip[m][:, [mch.index(c) for c in ten]]))}, | |
| {"set": sname, "n": int(m.sum()), "pair": "real <-> GigaTIME (10 shared ch)", "R@1_g100": g100(rg(R10), rg(G10))}] | |
| Rt = pd.DataFrame(Rt) | |
| pd.set_option("display.width", 200) | |
| print(C.round(3).to_string(index=False)) | |
| print("\nmean over channels\n", C.groupby("set")[[c for c in C.columns if c not in ("channel", "set")]].mean().round(3).to_string()) | |
| print("\nmean over the 10 GigaTIME-shared channels\n", C[C.channel.isin(ten)].groupby("set")[[c for c in C.columns if c not in ("channel", "set")]].mean().round(3).to_string()) | |
| print("\n", Rt.round(3).to_string(index=False)) | |
| C.round(4).to_csv(os.path.join(OUT, "miphei_diag.csv"), index=False) | |
| Rt.round(4).to_csv(os.path.join(OUT, "miphei_diag_retrieval.csv"), index=False) | |