Skip to content

Commit

Permalink
Computed normalization stats for stacked windowed transform and some …
Browse files Browse the repository at this point in the history
…minor fixes
  • Loading branch information
MrinalJain17 committed Oct 19, 2020
1 parent c27c9a5 commit d7996cc
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 46 deletions.
41 changes: 19 additions & 22 deletions capstone/data/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,36 @@
from torch.utils.data import Dataset


class _MiccaiDataset2D(Dataset):
def __init__(self, path: str) -> None:
class MiccaiDataset2D(Dataset):
"""TODO
"""

def __init__(self, path: str, structure: str = None, transform=None) -> None:
self.path = Path(path).absolute()
self.structure_required = structure
self.transform = transform

self.instance_paths = []
for instance in self.path.iterdir():
self.instance_paths.append(instance.as_posix())
self.instance_paths.sort() # To get same order on Windows and Linux (cluster)

if self.structure_required is not None:
assert (
self.structure_required in miccai.STRUCTURES
), "Invalid structure name passed"

def __len__(self) -> int:
return len(self.instance_paths)

def __getitem__(self, index: int):
raise NotImplementedError()


class MiccaiDataset2D(_MiccaiDataset2D):
"""TODO
"""

def __init__(self, path: str, structure: str = None, transform=None) -> None:
super(MiccaiDataset2D, self).__init__(path)
if structure is not None:
assert structure in miccai.STRUCTURES, "Invalid structure name"
self.structure_required = structure
self.transform = transform

def __getitem__(self, index: int) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
instance = np.load(self.instance_paths[index])
image = np.transpose(instance["image"], (1, 2, 0))
masks, mask_indicator = instance["masks"], instance["mask_indicator"]

assert len(mask_indicator) == 9
assert masks.shape[0] == 9
assert len(mask_indicator) == len(miccai.STRUCTURES)
assert masks.shape[0] == len(miccai.STRUCTURES)

masks = list(masks)

Expand All @@ -52,8 +47,10 @@ def __getitem__(self, index: int) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:

if self.structure_required is not None:
idx = miccai.STRUCTURES.index(self.structure_required)
masks = masks[idx]
mask_indicator = mask_indicator[idx]
masks = np.expand_dims(masks[idx], axis=0)
mask_indicator = np.expand_dims(mask_indicator[idx], axis=0)
else:
masks = np.stack(masks)

return image, masks, mask_indicator

Expand Down
94 changes: 89 additions & 5 deletions capstone/notebooks/miccai_batch_exploration.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"%matplotlib inline\n",
"\n",
"from capstone.utils import miccai, visualize\n",
"from capstone.paths import DEFAULT_DATA_STORAGE"
"from capstone.paths import DEFAULT_DATA_STORAGE\n",
"from capstone.transforms.transforms_2d import apply_window, WINDOWING_CONFIG"
]
},
{
Expand All @@ -46,7 +47,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:28<00:00, 3.55s/it]\n"
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:42<00:00, 4.09s/it]\n"
]
},
{
Expand Down Expand Up @@ -158,7 +159,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:24<00:00, 3.38s/it]\n"
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:28<00:00, 3.56s/it]\n"
]
}
],
Expand Down Expand Up @@ -231,7 +232,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:04<00:00, 2.59s/it]"
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:04<00:00, 2.58s/it]"
]
},
{
Expand Down Expand Up @@ -286,7 +287,7 @@
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:17<00:00, 3.11s/it]\n"
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:23<00:00, 3.33s/it]\n"
]
}
],
Expand Down Expand Up @@ -357,6 +358,89 @@
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def window_stats(patient, window, crop=True):\n",
" temp_patient = patient\n",
" window_width, window_level = window\n",
" if crop:\n",
" temp_patient.crop_data()\n",
" \n",
" vol = temp_patient.image.as_numpy()\n",
" clipped = apply_window(vol, window_width, window_level, shift=True)\n",
" N = np.prod(vol.shape)\n",
" \n",
" return clipped.sum(), clipped.var() * N, N"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:09<00:00, 2.78s/it]\n",
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:12<00:00, 2.88s/it]\n",
"100%|██████████████████████████████████████████████████████████████████████████████████| 25/25 [01:08<00:00, 2.76s/it]\n"
]
}
],
"source": [
"# Brain windowing\n",
"results_brain = patient_collection.apply_function(window_stats, window=WINDOWING_CONFIG[\"brain\"])\n",
"\n",
"# Soft tissue windowing\n",
"results_tissue = patient_collection.apply_function(window_stats, window=WINDOWING_CONFIG[\"soft_tissue\"])\n",
"\n",
"# Bone windowing\n",
"results_bone = patient_collection.apply_function(window_stats, window=WINDOWING_CONFIG[\"bone\"])"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Brain windowing stats: mean=0.10677633102763491, std=0.2708013287518585\n",
"Soft tissue windowing stats: mean=0.13461463937176568, std=0.2668329203556111\n",
"Bone windowing stats: mean=0.08499418334609993, std=0.1520881280521281\n"
]
}
],
"source": [
"temp = np.array(list(results_brain.values()))\n",
"sum_means = temp[:, 0].sum()\n",
"sum_vars = temp[:, 1].sum()\n",
"sum_voxels = temp[:, 2].sum()\n",
"\n",
"print(f\"Brain windowing stats: mean={sum_means / sum_voxels}, std={np.sqrt(sum_vars / sum_voxels)}\")\n",
"\n",
"temp = np.array(list(results_tissue.values()))\n",
"sum_means = temp[:, 0].sum()\n",
"sum_vars = temp[:, 1].sum()\n",
"sum_voxels = temp[:, 2].sum()\n",
"\n",
"print(f\"Soft tissue windowing stats: mean={sum_means / sum_voxels}, std={np.sqrt(sum_vars / sum_voxels)}\")\n",
"\n",
"temp = np.array(list(results_bone.values()))\n",
"sum_means = temp[:, 0].sum()\n",
"sum_vars = temp[:, 1].sum()\n",
"sum_voxels = temp[:, 2].sum()\n",
"\n",
"print(f\"Bone windowing stats: mean={sum_means / sum_voxels}, std={np.sqrt(sum_vars / sum_voxels)}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
12 changes: 6 additions & 6 deletions capstone/notebooks/miccai_per_patient_exploration.ipynb

Large diffs are not rendered by default.

38 changes: 26 additions & 12 deletions capstone/notebooks/sample_dataset_2d.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion capstone/utils/visualize.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def plot_windowed(patient: Patient, index: int = 0):
"subdural": (215, 75),
"stroke": (8, 32),
"temporal bones": (2800, 600),
"soft tissues": (375, 40),
"soft tissues": (350, 20),
} # Values taken from https://radiopaedia.org/articles/windowing-ct

num_cols = 2
Expand Down

0 comments on commit d7996cc

Please sign in to comment.