File size: 3,736 Bytes
c67be2b
5ed0fdb
 
c67be2b
dd7337f
 
c67be2b
 
 
5ed0fdb
 
c67be2b
cdf49bf
dd7337f
cdf49bf
dd7337f
 
cdf49bf
0428fca
c67be2b
 
5ed0fdb
 
c67be2b
cdf49bf
c67be2b
 
 
 
5ed0fdb
c67be2b
 
0428fca
 
c67be2b
dd7337f
5ed0fdb
 
0428fca
 
 
dd7337f
c67be2b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dd7337f
c67be2b
 
 
 
 
 
 
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
import gradio as gr
import numpy as np
import pandas as pd
import torch
from scipy import stats
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from huggingface_hub import hf_hub_download
from transformers import AutoConfig, AutoModel, AutoTokenizer

# --- Load model ---
print("Loading BulkRNABert...")
config = AutoConfig.from_pretrained("InstaDeepAI/BulkRNABert", trust_remote_code=True)
config.embeddings_layers_to_save = (4,)
tokenizer = AutoTokenizer.from_pretrained("InstaDeepAI/BulkRNABert", trust_remote_code=True)
model = AutoModel.from_pretrained("InstaDeepAI/BulkRNABert", config=config, trust_remote_code=True)
model.eval()

csv_path = hf_hub_download(repo_id="InstaDeepAI/BulkRNABert",
                           filename="data/tcga_sample.csv", repo_type="model")
ref_df = pd.read_csv(csv_path)
ref_genes = [c for c in ref_df.columns if c != "identifier"]
print(f"✓ Model ready. Required genes: {len(ref_genes)}")


def align_genes(df, required):
    out = pd.DataFrame(0.0, index=df.index, columns=required)
    for g in required:
        if g in df.columns:
            out[g] = df[g]
    return out


def embed(df):
    expr = np.log10(1 + df.to_numpy())
    ids = tokenizer.batch_encode_plus(expr, return_tensors="pt")["input_ids"]
    with torch.no_grad():
        out = model(ids)
    return out["embeddings_4"].mean(axis=1).numpy()


def analyze(tcga_file, cptac_file):
    """Novel analysis: signature vs embeddings."""
    if tcga_file is None or cptac_file is None:
        return {"error": "Upload both files"}

    # Load
    tcga = pd.read_csv(tcga_file.name, sep="\t", index_col=0).T
    cptac = pd.read_csv(cptac_file.name, sep="\t", index_col=0).T

    # Align and embed
    tcga_a = align_genes(tcga, ref_genes)
    cptac_a = align_genes(cptac, ref_genes)
    tcga_emb = embed(tcga_a)
    cptac_emb = embed(cptac_a)

    # PCA
    pca = PCA(n_components=5, random_state=42)
    tcga_pca = pca.fit_transform(tcga_emb)
    cptac_pca = pca.transform(cptac_emb)

    # Novel metric: eTNSI
    tcga_centroid = tcga_pca.mean(axis=0)
    cptac_centroid = cptac_pca.mean(axis=0)
    centroid_dist = float(np.linalg.norm(tcga_centroid - cptac_centroid))

    tcga_d = np.linalg.norm(tcga_pca - tcga_centroid, axis=1)
    cptac_d = np.linalg.norm(cptac_pca - tcga_centroid, axis=1)
    etnsi = float((cptac_d.mean() - tcga_d.mean()) / tcga_d.std())
    _, p_val = stats.mannwhitneyu(tcga_d, cptac_d)

    # Classifier
    X = np.vstack([tcga_pca, cptac_pca])
    y = np.array([0] * len(tcga_pca) + [1] * len(cptac_pca))
    clf = LogisticRegression(max_iter=1000, random_state=42)
    auc = cross_val_score(clf, X, y, cv=5, scoring="roc_auc")

    return {
        "status": "success",
        "tcga_samples": int(tcga_emb.shape[0]),
        "cptac_samples": int(cptac_emb.shape[0]),
        "embedding_dim": int(tcga_emb.shape[1]),
        "pca_variance_explained": float(pca.explained_variance_ratio_.sum()),
        "centroid_distance": centroid_dist,
        "etnsi_embedding": etnsi,
        "etnsi_pvalue": float(p_val),
        "classifier_auc_mean": float(auc.mean()),
        "classifier_auc_std": float(auc.std()),
    }


iface = gr.Interface(
    fn=analyze,
    inputs=[
        gr.File(label="TCGA expression TSV (genes × samples)"),
        gr.File(label="CPTAC expression TSV (genes × samples)"),
    ],
    outputs=gr.JSON(label="Novel Results"),
    title="BulkRNABert Novel Analysis",
    description="Correlates 9-gene signature with BulkRNABert embeddings. "
                "Outputs eTNSI and classifier AUC — novel metrics for UCEC.",
)

iface.launch(server_name="0.0.0.0", server_port=7860)