Skip to content

Commit

Permalink
86 tutorial updates (Project-MONAI#183)
Browse files Browse the repository at this point in the history
* update nifti read notebook

* revise notebook unet_segmentation_3d.ipynb

* revise transformations

        - revise Spacing transforms to rely on the affines only
        - rectified a few typos

* unit testing spacing transformations

* update docs

* update demo with spacing transform

* fixes padding mode spacing

* fixes load nifti

* 3d transform tutorial

* update notebooks

* revised spacing, load nifti for readability

* update example readme to include 3d transforms

* fixes tensor contiguous in spatial transforms, fixes docs

* update codecov xml for all branches

* [DLMED] update spleen notebook

Co-authored-by: Nic Ma <[email protected]>
  • Loading branch information
wyli and Nic-Ma authored Mar 27, 2020
1 parent e657db0 commit 8072028
Show file tree
Hide file tree
Showing 23 changed files with 1,667 additions and 610 deletions.
2 changes: 0 additions & 2 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ coverage:
target: 70%
threshold: 10
base: parent
branches: null
if_no_uploads: error
if_not_found: success
if_ci_failed: error
Expand All @@ -18,7 +17,6 @@ coverage:
# Allows PRs without tests, overall stats count
threshold: 100
base: auto
branches: null
if_no_uploads: error
if_not_found: success
if_ci_failed: error
Expand Down
25 changes: 14 additions & 11 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ python -m pip install -U notebook
```

### 2. List of examples
#### 1. [classification_3d](https://github.com/Project-MONAI/MONAI/tree/master/examples/classification_3d)
#### [classification_3d](./classification_3d)
Training and evaluation examples of 3D classification based on DenseNet3D and [IXI dataset](https://brain-development.org/ixi-dataset):
The examples are standard PyTorch programs and have both dictionary-based and array-based transformation versions.
#### 2. [classification_3d_ignite](https://github.com/Project-MONAI/MONAI/tree/master/examples/classification_3d_ignite)
#### [classification_3d_ignite](./classification_3d_ignite)
Training and evaluation examples of 3D classification based on DenseNet3D and [IXI dataset](https://brain-development.org/ixi-dataset):
The examples are PyTorch ignite programs and have both dictionary-based and array-based transformation versions.
#### 3. [notebooks/multi_gpu_test](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/multi_gpu_test.ipynb)
#### [notebooks/multi_gpu_test](./notebooks/multi_gpu_test.ipynb)
This notebook is a quick demo for devices, run the Ignite trainer engine on CPU, GPU and multiple GPUs.
#### 4. [notebooks/nifti_read_example](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/nifti_read_example.ipynb)
#### [notebooks/nifti_read_example](./notebooks/nifti_read_example.ipynb)
Illustrate reading NIfTI files and iterating over image patches of the volumes loaded from them.
#### 5. [notebooks/spleen_segmentation_3d](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/spleen_segmentation_3d.ipynb)
#### [notebooks/spleen_segmentation_3d](./notebooks/spleen_segmentation_3d.ipynb)
This notebook is an end-to-end training and evaluation example of 3D segmentation based on [MSD Spleen dataset](http://medicaldecathlon.com):
The example shows the flexibility of MONAI modules in a PyTorch-based program:
- Transforms for dictionary-based training data structure.
Expand All @@ -30,17 +30,20 @@ The example shows the flexibility of MONAI modules in a PyTorch-based program:
- 3D UNet, Dice loss function, Mean Dice metric for 3D segmentation task.
- Sliding window inference.
- Deterministic training for reproducibility.
#### 6. [notebooks/transform_speed](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/transform_speed.ipynb)
#### [notebooks/transform_speed](./notebooks/transform_speed.ipynb)
Illustrate reading NIfTI files and test speed of different transforms on different devices.
#### 7. [notebooks/transforms_demo_2d](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/transforms_demo_2d.ipynb)
This notebook demonstrates the medical domain specific transforms on 2D medical images.
#### 8. [notebooks/unet_segmentation_3d_ignite](https://github.com/Project-MONAI/MONAI/blob/master/examples/notebooks/unet_segmentation_3d_ignite.ipynb)
#### [notebooks/transforms_demo_2d](./notebooks/transforms_demo_2d.ipynb)
This notebook demonstrates the image transformations on histology images using
[the GlaS Contest dataset](https://warwick.ac.uk/fac/sci/dcs/research/tia/glascontest/download/).
#### [notebooks/3d_image_transforms](./notebooks/3D_image_transforms.ipynb)
This notebook demonstrates the transformations on volumetric images.
#### [notebooks/unet_segmentation_3d_ignite](./notebooks/unet_segmentation_3d_ignite.ipynb)
This notebook is an end-to-end training & evaluation example of 3D segmentation based on synthetic dataset.
The example is a PyTorch Ignite program and shows several key features of MONAI,
especially with medical domain specific transforms and event handlers.
#### 9. [segmentation_3d](https://github.com/Project-MONAI/MONAI/tree/master/examples/segmentation_3d)
#### [segmentation_3d](./examples/segmentation_3d)
Training and evaluation examples of 3D segmentation based on UNet3D and synthetic dataset.
The examples are standard PyTorch programs and have both dictionary-based and array-based versions.
#### 10. [segmentation_3d_ignite](https://github.com/Project-MONAI/MONAI/tree/master/examples/segmentation_3d_ignite)
#### [segmentation_3d_ignite](./examples/segmentation_3d_ignite)
Training and evaluation examples of 3D segmentation based on UNet3D and synthetic dataset.
The examples are PyTorch Ignite programs and have both dictionary-base and array-based transformations.
702 changes: 702 additions & 0 deletions examples/notebooks/3D_image_transforms.ipynb

Large diffs are not rendered by default.

84 changes: 28 additions & 56 deletions examples/notebooks/nifti_read_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@
{
"name": "stdout",
"output_type": "stream",
"text": "MONAI version: 0.0.1\nPython version: 3.8.1 (default, Jan 8 2020, 22:29:32) [GCC 7.3.0]\nNumpy version: 1.18.1\nPytorch version: 1.4.0\nIgnite version: 0.3.0\n"
"text": [
"MONAI version: 0.0.1\n",
"Python version: 3.5.6 |Anaconda, Inc.| (default, Aug 26 2018, 16:30:03) [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]\n",
"Numpy version: 1.18.2\n",
"Pytorch version: 1.4.0\n",
"Ignite version: 0.3.0\n"
]
}
],
"source": [
Expand All @@ -35,56 +41,18 @@
"\n",
"import torch\n",
"from torch.utils.data import DataLoader\n",
"import monai.transforms.compose as transforms\n",
"from monai.transforms.compose import Compose\n",
"\n",
"import monai\n",
"\n",
"from monai.transforms.utils import rescale_array\n",
"from monai.data.nifti_reader import NiftiDataset\n",
"from monai.transforms import AddChannel, Transpose, Rescale, ToTensor, RandUniformPatch\n",
"from monai.data.grid_dataset import GridPatchDataset\n",
"from monai.data.synthetic import create_test_image_3d\n",
"\n",
"monai.config.print_config()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define a function for creating test images and segmentations:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def create_test_image_3d(height, width, depth, numObjs=12, radMax=30, noiseMax=0.0, numSegClasses=5):\n",
" '''Return a noisy 3D image and segmentation.'''\n",
" image = np.zeros((width, height,depth))\n",
"\n",
" for i in range(numObjs):\n",
" x = np.random.randint(radMax, width - radMax)\n",
" y = np.random.randint(radMax, height - radMax)\n",
" z = np.random.randint(radMax, depth - radMax)\n",
" rad = np.random.randint(5, radMax)\n",
" spy, spx, spz = np.ogrid[-x:width - x, -y:height - y, -z:depth - z]\n",
" circle = (spx * spx + spy * spy + spz * spz) <= rad * rad\n",
"\n",
" if numSegClasses > 1:\n",
" image[circle] = np.ceil(np.random.random() * numSegClasses)\n",
" else:\n",
" image[circle] = np.random.random() * 0.5 + 0.5\n",
"\n",
" labels = np.ceil(image).astype(np.int32)\n",
"\n",
" norm = np.random.uniform(0, numSegClasses * noiseMax, size=image.shape)\n",
" noisyimage = rescale_array(np.maximum(image, norm))\n",
"\n",
" return noisyimage, labels"
]
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -94,14 +62,14 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"tempdir = tempfile.mkdtemp()\n",
"\n",
"for i in range(5):\n",
" im, seg = create_test_image_3d(256,256,256)\n",
" im, seg = create_test_image_3d(128, 128, 128)\n",
" \n",
" n = nib.Nifti1Image(im, np.eye(4))\n",
" nib.save(n, os.path.join(tempdir, 'im%i.nii.gz'%i))\n",
Expand All @@ -119,33 +87,35 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "torch.Size([5, 1, 64, 64, 64]) torch.Size([5, 256, 256, 256])\n"
"text": [
"torch.Size([5, 1, 64, 64, 64]) torch.Size([5, 1, 64, 64, 64])\n"
]
}
],
"source": [
"images = sorted(glob(os.path.join(tempdir,'im*.nii.gz')))\n",
"segs = sorted(glob(os.path.join(tempdir,'seg*.nii.gz')))\n",
"\n",
"imtrans=transforms.Compose([\n",
"imtrans = Compose([\n",
" Rescale(),\n",
" AddChannel(),\n",
" RandUniformPatch((64, 64, 64)),\n",
" ToTensor()\n",
"]) \n",
"\n",
"segtrans=transforms.Compose([\n",
"segtrans = Compose([\n",
" AddChannel(),\n",
" RandUniformPatch((64, 64, 64)),\n",
" ToTensor()\n",
"]) \n",
" \n",
"ds = NiftiDataset(images, segs, imtrans, segtrans)\n",
"ds = NiftiDataset(images, segs, transform=imtrans, seg_transform=segtrans)\n",
"\n",
"loader = DataLoader(ds, batch_size=10, num_workers=2, pin_memory=torch.cuda.is_available())\n",
"im, seg = monai.utils.misc.first(loader)\n",
Expand All @@ -161,28 +131,30 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": "torch.Size([10, 1, 64, 64, 64]) torch.Size([10, 256, 64, 64])\n"
"text": [
"torch.Size([10, 1, 64, 64, 64]) torch.Size([10, 1, 64, 64, 64])\n"
]
}
],
"source": [
"imtrans=transforms.Compose([\n",
"imtrans = Compose([\n",
" Rescale(),\n",
" AddChannel(),\n",
" ToTensor()\n",
"]) \n",
"\n",
"segtrans=transforms.Compose([\n",
"segtrans = Compose([\n",
" AddChannel(),\n",
" ToTensor()\n",
"]) \n",
" \n",
"ds = NiftiDataset(images, segs, imtrans, segtrans)\n",
"ds = NiftiDataset(images, segs, transform=imtrans, seg_transform=segtrans)\n",
"ds = GridPatchDataset(ds, (64, 64, 64))\n",
"\n",
"loader = DataLoader(ds, batch_size=10, num_workers=2, pin_memory=torch.cuda.is_available())\n",
Expand All @@ -192,7 +164,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -223,9 +195,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.1-final"
"version": "3.5.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
}
9 changes: 7 additions & 2 deletions examples/notebooks/spleen_segmentation_3d.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@
"import monai\n",
"import monai.transforms.compose as transforms\n",
"from monai.transforms.composables import \\\n",
" LoadNiftid, AddChanneld, ScaleIntensityRanged, RandCropByPosNegLabeld, RandAffined\n",
" LoadNiftid, AddChanneld, ScaleIntensityRanged, RandCropByPosNegLabeld, \\\n",
" RandAffined, Spacingd, Orientationd\n",
"from monai.data.utils import list_data_collate\n",
"from monai.utils.sliding_window_inference import sliding_window_inference\n",
"from monai.metrics.compute_meandice import compute_meandice\n",
Expand Down Expand Up @@ -115,6 +116,8 @@
"train_transforms = transforms.Compose([\n",
" LoadNiftid(keys=['image', 'label']),\n",
" AddChanneld(keys=['image', 'label']),\n",
" Spacingd(keys=['image', 'label'], pixdim=(1.5, 1.5, 2.), interp_order=(3, 0)),\n",
" Orientationd(keys=['image', 'label'], axcodes='RAS'),\n",
" ScaleIntensityRanged(keys=['image'], a_min=-57, a_max=164, b_min=0.0, b_max=1.0, clip=True),\n",
" # randomly crop out patch samples from big image based on pos / neg ratio\n",
" # the image centers of negative samples must be in valid image area\n",
Expand All @@ -127,6 +130,8 @@
"val_transforms = transforms.Compose([\n",
" LoadNiftid(keys=['image', 'label']),\n",
" AddChanneld(keys=['image', 'label']),\n",
" Spacingd(keys=['image', 'label'], pixdim=(1.5, 1.5, 2.), interp_order=(3, 0)),\n",
" Orientationd(keys=['image', 'label'], axcodes='RAS'),\n",
" ScaleIntensityRanged(keys=['image'], a_min=-57, a_max=164, b_min=0.0, b_max=1.0, clip=True)\n",
"])"
]
Expand Down Expand Up @@ -516,4 +521,4 @@
},
"nbformat": 4,
"nbformat_minor": 4
}
}
44 changes: 30 additions & 14 deletions examples/notebooks/transforms_demo_2d.ipynb

Large diffs are not rendered by default.

Loading

0 comments on commit 8072028

Please sign in to comment.