🛠️ util.py
Helper functions:
_onehot_enc(mask, num_classes): One-hot encoding of 3D masks,(B, 1, D, H, W)→(B, C, D, H, W)_onehot_enc_2d(mask, num_classes): One-hot encoding of 2D masks,(B, 1, H, W)or(B, H, W)→(B, C, H, W)_save_visualization_2d(...): Placeholder for saving 2D predictions (body currently commented out)
🛠️ pad_unpad.py
Functions for padding/unpadding inputs whose spatial size is not divisible by the U-Net stride (2**depth). Padding is zero-valued and split symmetrically.
pad_to_3d(x, stride)→(x_padded, pads);unpad_3d(x, pads)restores the original(D, H, W)sizepad_to_2d(x, stride)→(x_padded, pads);unpad_2d(x, pads)restores the original(H, W)size
Utilities to precompute BioBERT report embeddings (requires transformers):
hash_report(text): SHA1 of the lower-cased, whitespace-normalized report (identical reports share one embedding)image_stem(image_path): File name without extension (key of the image-to-report map)mean_pool(last_hidden_state, attention_mask): Masked mean pooling
precompute_unique_report_embeddings(dataloader, save_directory, model_name="dmis-lab/biobert-base-cased-v1.1", max_length=256, pooling="mean", device="cuda", overwrite=False, use_safetensors=True):
- Reads
textandimage_pathfrom each batch, deduplicates reports, and encodes each unique report once pooling:"mean"(masked mean) or"cls"(first token)- Skips the computation if all outputs already exist, unless
overwrite=True
Outputs in save_directory:
reports_emb.npy:[N_unique_reports, 768]float32 embeddingsimage_to_report_idx.json: image stem → row index inreports_emb.npyreports_meta.json: model name,max_length, pooling, embedding dim, number of unique reports, average tokens, report hash → indexavg_num_tokens.txt,total_num_tokens.txt: tokenization statistics
Only reports_emb.npy and image_to_report_idx.json are read by QaTaCovTextEmb.