File size: 3,690 Bytes
9a5439c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Synthetic captions (27_azure_caption.py, GPT, 3-shot PathGen style) -> per-set meta for 08_extract_text.py.
VALIDATION ONLY: these texts are never used to train any head.
Output cache/orion_gentext_meta.csv (row i = ORION tile_id i of load_all_tiles(); `caption` column)
"""
import json
import os

import pandas as pd

from common import CACHE, load_all_tiles

C = pd.DataFrame([json.loads(l) for l in open(os.path.join(CACHE, "gen_text", "captions.jsonl"))])
C = C[(C.set == "orion") & C.caption.notna() & (C.caption.str.len() > 0)].drop_duplicates("path", keep="last")
cap = dict(zip(C.path.map(os.path.basename), C.caption))
df = load_all_tiles()
df["caption"] = df.image_path.map(lambda p: cap.get(os.path.basename(p)))
print(f"ORION tiles {len(df)}, with synthetic caption {df.caption.notna().sum()}")
assert df.caption.notna().all(), "missing captions -> rerun 27_azure_caption.py (resumable)"
df[["tile_id", "image_path", "caption"]].to_csv(os.path.join(CACHE, "orion_gentext_meta.csv"), index=False)

# TCGA calibration set (27_ --sets tcga_calib): synthetic captions of patches that also have REAL text
A = pd.DataFrame([json.loads(l) for l in open(os.path.join(CACHE, "gen_text", "captions.jsonl"))])
A = A[(A.set == "tcga_calib") & A.caption.notna()].drop_duplicates("path", keep="last")
if len(A):
    I = pd.read_csv(os.path.join(CACHE, "allimg_meta.csv"))
    shots = [s["key"][:12] for s in json.load(open(os.path.join(CACHE, "gen_text", "prompt.json")))["shots"]]
    A["img_idx"] = A.path.map(dict(zip(I.image_path, I.index)))
    A = A[A.img_idx.notna() & ~A.img_idx.map(lambda i: I.patient[int(i)] in shots)]  # drop few-shot patients
    A["img_idx"] = A.img_idx.astype(int)
    A[["img_idx", "path", "caption"]].reset_index(drop=True).to_csv(os.path.join(CACHE, "tcga_calib_meta.csv"), index_label="idx")
    print(f"TCGA calibration captions: {len(A)} (few-shot patients excluded: {shots})")

# external test sets (27_ --sets dlpfc idc): row i = row i of cache/external/<set>_meta.csv
for st in ("dlpfc", "idc"):
    X = pd.DataFrame([json.loads(l) for l in open(os.path.join(CACHE, "gen_text", "captions.jsonl"))])
    X = X[(X.set == st) & X.caption.notna() & (X.caption.str.len() > 0)].drop_duplicates("key", keep="last")
    if not len(X):
        continue
    n = len(pd.read_csv(os.path.join(CACHE, "external", f"{st}_meta.csv")))
    cap = dict(zip(X.path.str.split(":").str[2].astype(int), X.caption))
    out = pd.DataFrame({"row": range(n), "caption": [cap.get(i) for i in range(n)]})
    print(f"{st}: {n} spots, with synthetic caption {out.caption.notna().sum()}")
    assert out.caption.notna().all(), "missing captions -> rerun 27_azure_caption.py --sets dlpfc idc (resumable)"
    out.to_csv(os.path.join(CACHE, f"{st}_gentext_meta.csv"), index=False)

# TCGA images without real text after junk removal (40_clean_text.py; 27_ --sets tcga_notext). A caption made for
# the same image under another set (tcga_calib) is reused. Row i of the output = row i of notext_meta.csv.
N = pd.read_csv(os.path.join(CACHE, "notext_meta.csv"))
X = pd.DataFrame([json.loads(l) for l in open(os.path.join(CACHE, "gen_text", "captions.jsonl"))])
X = X[X.caption.notna() & (X.caption.str.len() > 0)].drop_duplicates("path", keep="last")
cap = dict(zip(X.path.map(os.path.abspath), X.caption))
N["caption"] = N.image_path.map(lambda p: cap.get(os.path.abspath(p)))
print(f"TCGA no-text images {len(N)}, with synthetic caption {N.caption.notna().sum()}")
assert N.caption.notna().all(), "missing captions -> rerun 27_azure_caption.py --sets tcga_notext"
N[["img_idx", "image_path", "patient", "caption"]].to_csv(os.path.join(CACHE, "tcga_notext_meta.csv"), index=False)