| |
| """Sparsity analysis: how does unspliced detection rate affect gamma quality?""" |
| from _common import * |
|
|
| OUT = output_dir("05_sparsity") |
|
|
|
|
| def run(name, loader, _): |
| print(f"\n{'=' * 60}\n{name.upper()}\n{'=' * 60}") |
| adata = run_analytical(loader) |
| _, hl_human = load_halflife_refs() |
|
|
| from scipy.sparse import issparse |
| u = adata.layers["unspliced"] |
| if issparse(u): |
| u = np.asarray(u.todense()) |
| frac_det = (np.asarray(u) > 0).mean(axis=0) |
|
|
| g, h, names = match_halflife(adata, hl_human) |
| |
| det = np.array([frac_det[list(adata.var_names).index(n)] for n in names]) |
|
|
| quartiles = np.percentile(det, [25, 50, 75]) |
| bins = [ |
| ("Q1 (sparse)", det <= quartiles[0]), |
| ("Q2", (det > quartiles[0]) & (det <= quartiles[1])), |
| ("Q3", (det > quartiles[1]) & (det <= quartiles[2])), |
| ("Q4 (dense)", det > quartiles[2]), |
| ] |
|
|
| records = [] |
| for label, mask in bins: |
| if mask.sum() < 10: |
| continue |
| r, _ = stats.spearmanr(g[mask], h[mask]) |
| records.append({"quartile": label, "n": int(mask.sum()), |
| "r": float(r), "med_det": float(np.median(det[mask]))}) |
| print(f" {label}: r={r:.4f} (n={mask.sum()}, det={np.median(det[mask]):.3f})") |
|
|
| save_json({"dataset": name, "stratified": records}, f"{name}_sparsity", OUT) |
|
|
| fig, ax = plt.subplots(figsize=(7, 4)) |
| ax.bar([r["quartile"] for r in records], [abs(r["r"]) for r in records], |
| color="steelblue", alpha=0.7) |
| for i, r in enumerate(records): |
| ax.text(i, abs(r["r"]) + 0.005, f"n={r['n']}", ha="center", fontsize=8) |
| ax.set_ylabel("|Spearman r| with half-life") |
| ax.set_title(f"{name}: Half-life r by unspliced detection rate") |
| fig.tight_layout() |
| save_fig(fig, f"{name}_sparsity", OUT) |
| return records |
|
|
|
|
| def main(): |
| set_figure_style() |
| for name, loader, ck in DATASETS: |
| run(name, loader, ck) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|