Download scripts/common/generate_missing_holdouts.py from bryan7264/PANDA: direct link, hf CLI and curl.
- Browser
- Download file 3.43 kB
-
https://huggingface.co/bryan7264/PANDA/resolve/main/scripts/common/generate_missing_holdouts.py
- Command line
-
hf download hf://bryan7264/PANDA/scripts/common/generate_missing_holdouts.py
-
curl -L -o generate_missing_holdouts.py https://huggingface.co/bryan7264/PANDA/resolve/main/scripts/common/generate_missing_holdouts.py
3.43 kB
| """materialise held-out h5ad slices for nestorowa (hsc) and sulic (skin) using anchor split rules.""" | |
| from pathlib import Path | |
| import warnings, numpy as np, pandas as pd, anndata as ad, scanpy as sc, scipy.sparse as sp | |
| warnings.filterwarnings("ignore"); sc.settings.verbosity = 0 | |
| import os as _os | |
| from pathlib import Path as _Path | |
| PANDA_ROOT = _Path(_os.environ.get("PANDA_ROOT", str(_Path(__file__).resolve().parents[2]))) | |
| ROOT = Path(str(PANDA_ROOT)) | |
| def make_nestorowa_test(): | |
| src = ROOT / "data/raw/nestorowa_combined.h5ad" | |
| print(f"[nestorowa] loading {src}", flush=True) | |
| a = ad.read_h5ad(src) | |
| # anchor split from scripts/hematopoiesis/09_retrain_with_nestorowa_anchor.py: | |
| # 150 LT-HSC + 600 HSPC stratified (seed=0); rest is test. | |
| rng = np.random.default_rng(0) | |
| lt = np.where(a.obs["cell_type"].astype(str).values == "LT-HSC")[0] | |
| hs = np.where(a.obs["cell_type"].astype(str).values == "HSPC")[0] | |
| lt_anchor = rng.choice(lt, size=min(150, len(lt)), replace=False) | |
| hs_anchor = rng.choice(hs, size=min(600, len(hs)), replace=False) | |
| anchor_ix = np.concatenate([lt_anchor, hs_anchor]) | |
| test_ix = np.setdiff1d(np.arange(a.n_obs), anchor_ix) | |
| a_test = a[test_ix].copy() | |
| # coerce obs cols to string so h5ad write survives mixed dtypes | |
| for c in list(a_test.obs.columns): | |
| try: a_test.obs[c] = a_test.obs[c].astype(str) | |
| except Exception: del a_test.obs[c] | |
| out_dir = ROOT / "data/corpus/hematopoiesis/held_out_labeled" | |
| out_dir.mkdir(parents=True, exist_ok=True) | |
| out = out_dir / "nestorowa_GSE81682_test.h5ad" | |
| a_test.write_h5ad(out) | |
| print(f"[nestorowa] wrote {out} ({a_test.n_obs:,} cells; " | |
| f"gate dist: {a_test.obs['cell_type'].value_counts().to_dict()})", flush=True) | |
| def make_sulic_test(): | |
| corpus = ROOT / "data/corpus/pan_skin/harmonized/corpus.h5ad" | |
| print(f"[sulic] loading {corpus} (legacy, has sulic + labels)", flush=True) | |
| a = ad.read_h5ad(corpus) | |
| a_sul = a[a.obs["dataset"] == "sulic_GSE212673"].copy() | |
| print(f"[sulic] {a_sul.n_obs} sulic cells " | |
| f"({a_sul.obs['canonical_label'].value_counts().to_dict()})", flush=True) | |
| # anchor split from scripts/pan_skin/92_retrain_with_sulic_anchor.py: | |
| # 300 HF-placode + 200 basal-IFE stratified (seed=0); rest (4183) is test. | |
| rng = np.random.default_rng(0) | |
| hf = np.where(a_sul.obs["canonical_label"].astype(str).values == "HF-placode")[0] | |
| bi = np.where(a_sul.obs["canonical_label"].astype(str).values == "basal-IFE")[0] | |
| hf_anchor = rng.choice(hf, size=min(300, len(hf)), replace=False) | |
| bi_anchor = rng.choice(bi, size=min(200, len(bi)), replace=False) | |
| anchor_ix = np.concatenate([hf_anchor, bi_anchor]) | |
| test_ix = np.setdiff1d(np.arange(a_sul.n_obs), anchor_ix) | |
| a_test = a_sul[test_ix].copy() | |
| for c in list(a_test.obs.columns): | |
| try: a_test.obs[c] = a_test.obs[c].astype(str) | |
| except Exception: del a_test.obs[c] | |
| out_dir = ROOT / "data/corpus/pan_skin/held_out_labeled" | |
| out_dir.mkdir(parents=True, exist_ok=True) | |
| out = out_dir / "sulic_GSE212673_test.h5ad" | |
| a_test.write_h5ad(out) | |
| print(f"[sulic] wrote {out} ({a_test.n_obs:,} cells; " | |
| f"labels: {a_test.obs['canonical_label'].value_counts().to_dict()})", flush=True) | |
| if __name__ == "__main__": | |
| make_nestorowa_test() | |
| make_sulic_test() | |