Download experiments/manifest_data.py from Angione-Lab/Shape2Force: direct link, hf CLI and curl.
- Browser
- Download file 4.47 kB
-
https://huggingface.co/Angione-Lab/Shape2Force/resolve/main/experiments/manifest_data.py
- Command line
-
hf download hf://Angione-Lab/Shape2Force/experiments/manifest_data.py
-
curl -L -o manifest_data.py https://huggingface.co/Angione-Lab/Shape2Force/resolve/main/experiments/manifest_data.py
4.47 kB
| """ | |
| Manifest-based data loading. Uses exactly the preprocessing of the S2F package | |
| (``data.cell_dataset.load_image`` -> grayscale, resize to 1024, /255; ``ImageDataset``; | |
| ``AdvancedAugmentations``), so results are comparable with the released models. | |
| substrate_mode (single-cell only) decides which substrate setting builds the two substrate channels: | |
| 'legacy' what the original training code fed (derived from the all_tune folder name) - default, | |
| reproduces the conditions under which the released model was trained | |
| 'nominal' the true Young's modulus / TFM pixel-size setting of each sample | |
| 'reference' the 6 kPa reference setting (fibroblasts_PDMS) for every sample | |
| 'none' no metadata (models without substrate channels) | |
| input_mode: | |
| 'bf' bright-field image (default) | |
| 'mask' binary cell mask (file cell_mask.tif/png in the sample folder) - mask-only baseline | |
| """ | |
| import os | |
| import numpy as np | |
| import torch | |
| from torch.utils.data import DataLoader | |
| from data.cell_dataset import ImageDataset, load_image | |
| from experiments.layout import DEFAULT_DATASET_ROOT, MASK_NAMES, manifest_path, read_manifest | |
| def _find(folder, suffix=None, names=None): | |
| for f in sorted(os.listdir(folder)): | |
| if (suffix and f.endswith(suffix)) or (names and f in names): | |
| return os.path.join(folder, f) | |
| return None | |
| def load_manifest_pairs(manifest, dataset_root=DEFAULT_DATASET_ROOT, img_size=1024, | |
| substrate_mode="legacy", input_mode="bf"): | |
| rows = read_manifest(manifest if os.path.isfile(manifest) else manifest_path(manifest)) | |
| pairs = [] | |
| for r in rows: | |
| d = os.path.join(dataset_root, r["sample_dir"]) | |
| bf = _find(d, suffix="BF_001.tif") | |
| hm = _find(d, suffix="_gray.jpg") | |
| if bf is None or hm is None: | |
| raise FileNotFoundError(f"missing BF/heatmap in {d}") | |
| if input_mode == "mask": | |
| mp = _find(d, names=MASK_NAMES) | |
| if mp is None: | |
| raise FileNotFoundError(f"input_mode='mask' but no {MASK_NAMES} in {d}") | |
| x = (load_image(mp, (img_size, img_size)) > 0.5).astype(np.float32) | |
| else: | |
| x = load_image(bf, (img_size, img_size)) | |
| y = load_image(hm, (img_size, img_size)) | |
| if substrate_mode == "none": | |
| pairs.append((x, y, (0, 0))) | |
| continue | |
| sub = {"legacy": r.get("substrate_legacy"), "nominal": r.get("substrate_nominal"), | |
| "reference": "fibroblasts_PDMS"}[substrate_mode] or "fibroblasts_PDMS" | |
| pairs.append((x, y, (0, 0), {"folder_name": os.path.basename(d), "substrate": sub, | |
| "root_folder": os.path.dirname(r["sample_dir"]), "set": r.get("set", "")})) | |
| return pairs, rows | |
| def _worker_init(worker_id): | |
| """Distinct, reproducible numpy seed per worker (augmentations use np.random). Module-level for Windows spawn.""" | |
| np.random.seed(torch.initial_seed() % 2 ** 32) | |
| class _MaskDataset(ImageDataset): | |
| """Re-binarise the input after augmentation (intensity augmentations are meaningless for masks).""" | |
| def __getitem__(self, idx): | |
| out = list(super().__getitem__(idx)) | |
| out[0] = (out[0] > 0.5).float() | |
| return tuple(out) | |
| def make_loader(manifest, dataset_root=DEFAULT_DATASET_ROOT, batch_size=2, img_size=1024, augment=False, | |
| shuffle=False, substrate_mode="legacy", input_mode="bf", seed=None, num_workers=0): | |
| pairs, rows = load_manifest_pairs(manifest, dataset_root, img_size, substrate_mode, input_mode) | |
| transform = None | |
| if augment: | |
| from data.augmentations import AdvancedAugmentations | |
| transform = AdvancedAugmentations((img_size, img_size)) | |
| cls = _MaskDataset if input_mode == "mask" else ImageDataset | |
| ds = cls(pairs, transform=transform, channel_first=True, threshold=0.0, | |
| return_metadata=substrate_mode != "none") | |
| ds.rows = rows | |
| g = None | |
| if seed is not None: | |
| g = torch.Generator(); g.manual_seed(seed) | |
| if num_workers > 0: # workers run the augmentations so the GPU is not left waiting | |
| return DataLoader(ds, batch_size=batch_size, shuffle=shuffle, generator=g, num_workers=num_workers, | |
| persistent_workers=True, pin_memory=torch.cuda.is_available(), | |
| worker_init_fn=_worker_init) | |
| return DataLoader(ds, batch_size=batch_size, shuffle=shuffle, generator=g, num_workers=0) | |