| """Extract PET/SUVR embeddings and per-subject predictions for paper figures.""" |
| import sys, os, argparse |
| sys.path.insert(0, os.path.dirname(__file__)) |
| import numpy as np |
| import torch |
| from pathlib import Path |
| from torch.utils.data import DataLoader |
| from pet_vlm_dataset import PETSUVRDataset, collate_pet_suvr |
| from train_pet_foundation import PETSUVRFoundationModel, build_encoder |
|
|
| def make_args(backbone): |
| args = argparse.Namespace() |
| args.backbone = backbone |
| args.medicalnet_weights = Path("pretrained/medicalnet/resnet_50_23dataset.pth") |
| args.brainiac_weights = Path("pretrained/brainiac/backbone.safetensors") |
| args.brainfm_weights = Path("pretrained/brainfm/assets/brainfm_pretrained.pth") |
| args.brainfm_code_root = Path("pretrained/brainfm") |
| args.swinunetr_weights = Path("pretrained/swinunetr/model_swinvit.pt") |
| args.sam_med3d_weights = Path("pretrained/sam-med3d/sam_med3d_turbo.pth") |
| args.output_size = [96, 96, 96] |
| return args |
|
|
| def extract(checkpoint_path, backbone, output_prefix): |
| device = torch.device("cuda:0") |
| args = make_args(backbone) |
| output_size = tuple(args.output_size) |
|
|
| encoder = build_encoder(args) |
| n_regions = 120 |
| model = PETSUVRFoundationModel(encoder, n_regions=n_regions).to(device) |
|
|
| ckpt = torch.load(checkpoint_path, map_location=device, weights_only=False) |
| model.load_state_dict(ckpt["model"], strict=False) |
| model.eval() |
|
|
| ds = PETSUVRDataset(Path("metadata/splits/test.csv"), output_size=output_size) |
| loader = DataLoader(ds, batch_size=4, shuffle=False, num_workers=2, collate_fn=collate_pet_suvr) |
|
|
| pet_zs, suvr_zs, preds, targets = [], [], [], [] |
| with torch.no_grad(): |
| for batch in loader: |
| img = batch["image"].to(device) |
| suvr = batch["suvr"].to(device) |
| outputs = model(img, suvr) |
|
|
| pet_feat = model.pet_encoder(img) |
| pet_z = torch.nn.functional.normalize(model.pet_projector(pet_feat), dim=-1) |
| suvr_z = torch.nn.functional.normalize(model.suvr_encoder(suvr), dim=-1) |
|
|
| pet_zs.append(pet_z.cpu().numpy()) |
| suvr_zs.append(suvr_z.cpu().numpy()) |
| preds.append(outputs["pred_suvr"].cpu().numpy()) |
| targets.append(suvr.cpu().numpy()) |
|
|
| pet_zs = np.concatenate(pet_zs) |
| suvr_zs = np.concatenate(suvr_zs) |
| preds = np.concatenate(preds) |
| targets = np.concatenate(targets) |
|
|
| out_dir = Path("runs/paper_figures") |
| out_dir.mkdir(exist_ok=True) |
| np.savez(out_dir / f"{output_prefix}_embeddings.npz", |
| pet_z=pet_zs, suvr_z=suvr_zs, pred_suvr=preds, true_suvr=targets) |
| print(f"Saved {output_prefix}: pet_z={pet_zs.shape}, suvr_z={suvr_zs.shape}, pred={preds.shape}") |
|
|
| if __name__ == "__main__": |
| os.chdir("/data/Albus/Brain") |
| extract("runs/foundation/medicalnet_layer4_regalign_best.pt", "medicalnet", "remap_pet") |
| extract("runs/foundation/medicalnet_frozen_mlp.pt", "medicalnet", "medicalnet_frozen") |
| print("Done!") |
|
|