diff --git a/generation/3d_ddpm/3d_ddpm_tutorial.ipynb b/generation/3d_ddpm/3d_ddpm_tutorial.ipynb new file mode 100644 index 000000000..c5067fc72 --- /dev/null +++ b/generation/3d_ddpm/3d_ddpm_tutorial.ipynb @@ -0,0 +1,795 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6286986e", + "metadata": {}, + "source": [ + "Copyright (c) MONAI Consortium \n", + "Licensed under the Apache License, Version 2.0 (the \"License\"); \n", + "you may not use this file except in compliance with the License. \n", + "You may obtain a copy of the License at \n", + "    http://www.apache.org/licenses/LICENSE-2.0 \n", + "Unless required by applicable law or agreed to in writing, software \n", + "distributed under the License is distributed on an \"AS IS\" BASIS, \n", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. \n", + "See the License for the specific language governing permissions and \n", + "limitations under the License.\n", + "\n", + "# Denoising Diffusion Probabilistic Model on 3D data\n", + "\n", + "This tutorial illustrates how to use MONAI for training a denoising diffusion probabilistic model (DDPM)[1] to create synthetic 3D images.\n", + "\n", + "[1] - [Ho et al. \"Denoising Diffusion Probabilistic Models\"](https://arxiv.org/abs/2006.11239)\n", + "\n", + "\n", + "## Setup environment" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f96b6f31", + "metadata": {}, + "outputs": [], + "source": [ + "!python -c \"import monai\" || pip install -q \"monai-weekly[nibabel, tqdm]\"\n", + "!python -c \"import matplotlib\" || pip install -q matplotlib\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "id": "cbc01d24", + "metadata": {}, + "source": [ + "## Setup imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdea37d5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MONAI version: 1.4.0\n", + "Numpy version: 1.26.4\n", + "Pytorch version: 2.4.0+cu121\n", + "MONAI flags: HAS_EXT = False, USE_COMPILED = False, USE_META_DICT = False\n", + "MONAI rev id: 46a5272196a6c2590ca2589029eed8e4d56ff008\n", + "MONAI __file__: /home//miniconda3/envs/monai/lib/python3.9/site-packages/monai/__init__.py\n", + "\n", + "Optional dependencies:\n", + "Pytorch Ignite version: 0.4.11\n", + "ITK version: 5.3.0\n", + "Nibabel version: 5.2.1\n", + "scikit-image version: 0.22.0\n", + "scipy version: 1.13.0\n", + "Pillow version: 10.3.0\n", + "Tensorboard version: 2.16.2\n", + "gdown version: 5.2.0\n", + "TorchVision version: NOT INSTALLED or UNKNOWN VERSION.\n", + "tqdm version: 4.66.4\n", + "lmdb version: 1.4.1\n", + "psutil version: 5.9.0\n", + "pandas version: 2.2.2\n", + "einops version: 0.8.0\n", + "transformers version: 4.40.2\n", + "mlflow version: 2.12.2\n", + "pynrrd version: 1.0.0\n", + "clearml version: 1.16.0rc0\n", + "\n", + "For details about installing the optional dependencies, please visit:\n", + " https://docs.monai.io/en/latest/installation.html#installing-the-recommended-dependencies\n", + "\n" + ] + } + ], + "source": [ + "import os\n", + "import tempfile\n", + "import time\n", + "import shutil\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import torch\n", + "import torch.nn.functional as F\n", + "from torch.amp import GradScaler, autocast\n", + "from tqdm import tqdm\n", + "\n", + "from monai.apps import DecathlonDataset\n", + "from monai.config import print_config\n", + "from monai.data import DataLoader\n", + "from monai.transforms import (\n", + " EnsureChannelFirstd,\n", + " CenterSpatialCropd,\n", + " Compose,\n", + " Lambdad,\n", + " LoadImaged,\n", + " Resized,\n", + " ScaleIntensityd,\n", + ")\n", + "from monai.utils import first, set_determinism\n", + "from monai.inferers import DiffusionInferer\n", + "from monai.networks.nets import DiffusionModelUNet\n", + "from monai.networks.schedulers import DDPMScheduler, DDIMScheduler\n", + "\n", + "print_config()" + ] + }, + { + "cell_type": "markdown", + "id": "50e37a43", + "metadata": {}, + "source": [ + "## Setup data directory\n", + "\n", + "You can specify a directory with the MONAI_DATA_DIRECTORY environment variable.\n", + "\n", + "This allows you to save results and reuse downloads.\n", + "\n", + "If not specified a temporary directory will be used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c38b4c33", + "metadata": {}, + "outputs": [], + "source": [ + "directory = os.environ.get(\"MONAI_DATA_DIRECTORY\")\n", + "root_dir = tempfile.mkdtemp() if directory is None else directory" + ] + }, + { + "cell_type": "markdown", + "id": "41af1391", + "metadata": {}, + "source": [ + "## Set deterministic training for reproducibility" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "515d8583", + "metadata": {}, + "outputs": [], + "source": [ + "set_determinism(42)" + ] + }, + { + "cell_type": "markdown", + "id": "29d8c601", + "metadata": {}, + "source": [ + "## Setup Decathlon Dataset and training and validation data loaders\n", + "\n", + "In this tutorial, we will use the 3D T1 weighted brain images from the [2016 and 2017 Brain Tumor Segmentation (BraTS) challenges](https://www.med.upenn.edu/sbia/brats2017/data.html). This dataset can be easily downloaded using the [DecathlonDataset](https://docs.monai.io/en/stable/apps.html#monai.apps.DecathlonDataset) from MONAI (`task=\"Task01_BrainTumour\"`). To load the training and validation images, we are using the `data_transform` transformations that are responsible for the following:\n", + "\n", + "1. `LoadImaged`: Loads the brain images from files.\n", + "2. `Lambdad`: Choose channel 1 of the image, which is the T1-weighted image.\n", + "3. `EnsureChannelFirstd`: Add the channel dimension of the input data.\n", + "4. `ScaleIntensityd`: Apply a min-max scaling in the intensity values of each image to be in the `[0, 1]` range.\n", + "5. `CenterSpatialCropd`: Crop the background of the images using a roi of size `[160, 200, 155]`.\n", + "6. `Resized`: Resize the images to a volume with size `[32, 40, 32]`.\n", + "\n", + "For the data loader, we are using mini-batches of 16 images, which consumes about 11GB of GPU memory during training. Please, reduce this value to run on smaller GPUs." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "f640d7ac", + "metadata": {}, + "outputs": [], + "source": [ + "data_transform = Compose(\n", + " [\n", + " LoadImaged(keys=[\"image\"]),\n", + " Lambdad(keys=\"image\", func=lambda x: x[:, :, :, 1]),\n", + " EnsureChannelFirstd(keys=[\"image\"], channel_dim=\"no_channel\"),\n", + " ScaleIntensityd(keys=[\"image\"]),\n", + " CenterSpatialCropd(keys=[\"image\"], roi_size=[160, 200, 155]),\n", + " Resized(keys=[\"image\"], spatial_size=(32, 40, 32)),\n", + " ]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ddd61e60", + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Loading dataset: 100%|██████████| 388/388 [01:57<00:00, 3.29it/s]\n", + "Loading dataset: 100%|██████████| 96/96 [00:30<00:00, 3.13it/s]\n" + ] + } + ], + "source": [ + "batch_size = 16\n", + "num_workers = 8\n", + "\n", + "train_ds = DecathlonDataset(\n", + " root_dir=root_dir,\n", + " task=\"Task01_BrainTumour\",\n", + " transform=data_transform,\n", + " section=\"training\",\n", + " download=True,\n", + " num_workers=num_workers,\n", + ")\n", + "\n", + "train_loader = DataLoader(\n", + " train_ds, batch_size=batch_size, shuffle=True, num_workers=num_workers, persistent_workers=True\n", + ")\n", + "\n", + "val_ds = DecathlonDataset(\n", + " root_dir=root_dir,\n", + " task=\"Task01_BrainTumour\",\n", + " transform=data_transform,\n", + " section=\"validation\",\n", + " download=True,\n", + " num_workers=num_workers,\n", + ")\n", + "\n", + "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=num_workers, persistent_workers=True)" + ] + }, + { + "cell_type": "markdown", + "id": "50efe5ef", + "metadata": {}, + "source": [ + "### Visualization of the training images" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "bffb4abc", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.subplots(1, 4, figsize=(10, 6))\n", + "for i in range(4):\n", + " plt.subplot(1, 4, i + 1)\n", + " plt.imshow(train_ds[i * 20][\"image\"][0, :, :, 15].detach().cpu(), vmin=0, vmax=1, cmap=\"gray\")\n", + " plt.axis(\"off\")\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "efc86997", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "img = first(item[\"image\"] for item in train_ds if \"400\" in item[\"image\"].meta[\"filename_or_obj\"])\n", + "imgn = img[0].detach().cpu().numpy()\n", + "f, (ax0, ax1, ax2, ax3) = plt.subplots(1, 4)\n", + "ax0.imshow(imgn[..., 15], vmin=0, vmax=1, cmap=\"gray\")\n", + "ax1.imshow(np.max(imgn, axis=0), vmin=0, vmax=1, cmap=\"gray\")\n", + "ax2.imshow(np.max(imgn, axis=1), vmin=0, vmax=1, cmap=\"gray\")\n", + "ax3.imshow(np.max(imgn, axis=2), vmin=0, vmax=1, cmap=\"gray\")" + ] + }, + { + "cell_type": "markdown", + "id": "d22296e5", + "metadata": {}, + "source": [ + "### Define network, scheduler, optimizer, and inferer\n", + "\n", + "We will use a DDPM in this example; for that, we need to define a `DiffusionModelUNet` network that will have as input the noisy images and the values for the timestep `t`, and it will predict the noise that is present in the image.\n", + "\n", + "In this example, we have a network with three levels (with 256, 256, and 512 channels in each). In every level, we will have two residual blocks, and only the last one will have an attention block with a single attention head (with 512 channels)." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d499f7b1", + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [], + "source": [ + "device = torch.device(\"cuda\")\n", + "\n", + "model = DiffusionModelUNet(\n", + " spatial_dims=3,\n", + " in_channels=1,\n", + " out_channels=1,\n", + " channels=[64, 64, 128],\n", + " attention_levels=[False, False, True],\n", + " num_head_channels=[0, 0, 128],\n", + " num_res_blocks=2,\n", + ").to(device)" + ] + }, + { + "cell_type": "markdown", + "id": "47ad91ff", + "metadata": {}, + "source": [ + "Together with our U-net, we need to define the Noise Scheduler for the diffusion model. This scheduler is responsible for defining the amount of noise that should be added in each timestep `t` of the diffusion model's Markov chain. Besides that, it has the operations to perform the reverse process, which will remove the noise of the images (a.k.a. denoising process). In this case, we are using a `DDPMScheduler`. Here we are using 1000 timesteps and a `scaled_linear` profile for the beta values (proposed in [Rombach et al. \"High-Resolution Image Synthesis with Latent Diffusion Models\"](https://arxiv.org/abs/2112.10752)). This profile had better results than the `linear, proposed in the original DDPM's paper. In `beta_start` and `beta_end`, we define the limits for the beta values. These are important to determine how accentuated is the addition of noise in the image." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "6c1de5ad", + "metadata": {}, + "outputs": [], + "source": [ + "num_train_timesteps = 1000\n", + "scheduler = DDPMScheduler(\n", + " num_train_timesteps=num_train_timesteps,\n", + " schedule=\"scaled_linear_beta\",\n", + " beta_start=0.0005,\n", + " beta_end=0.0195,\n", + " clip_sample=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "36d3e99a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0, 0.5, 'alpha cumprod')" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(scheduler.alphas_cumprod.cpu(), color=(2 / 255, 163 / 255, 163 / 255), linewidth=2)\n", + "plt.xlabel(\"Timestep [t]\")\n", + "plt.ylabel(\"alpha cumprod\")" + ] + }, + { + "cell_type": "markdown", + "id": "9125f7c8", + "metadata": {}, + "source": [ + "Finally, we define the Inferer, which contains functions that will help during the training and sampling of the model, and the optimizer." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "8685da6e", + "metadata": {}, + "outputs": [], + "source": [ + "inferer = DiffusionInferer(scheduler)\n", + "optimizer = torch.optim.Adam(params=model.parameters(), lr=5e-5)" + ] + }, + { + "cell_type": "markdown", + "id": "9f371ad8", + "metadata": {}, + "source": [ + "## Model training\n", + "\n", + "In this part, we will train the diffusion model to predict the noise added to the images. For this, we are using an MSE loss between the prediction and the original noise. During the training, we are also sampling brain images to evaluate the evolution of the model. In this training, we use Automatic Mixed Precision to save memory and speed up the training." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "bd10b595", + "metadata": { + "lines_to_next_cell": 0 + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Epoch 00: 100%|██████████| 25/25 [00:35<00:00, 1.41s/it, loss=0.8318]\n", + "Epoch 01: 100%|██████████| 25/25 [00:35<00:00, 1.43s/it, loss=0.4999]\n", + "Epoch 02: 100%|██████████| 25/25 [00:37<00:00, 1.48s/it, loss=0.2719]\n", + "Epoch 03: 100%|██████████| 25/25 [00:36<00:00, 1.47s/it, loss=0.1401]\n", + "Epoch 04: 100%|██████████| 25/25 [00:36<00:00, 1.47s/it, loss=0.0709]\n", + "Epoch 05: 100%|██████████| 25/25 [00:37<00:00, 1.48s/it, loss=0.0394]\n", + "Epoch 06: 100%|██████████| 25/25 [00:36<00:00, 1.48s/it, loss=0.0207]\n", + "Epoch 07: 100%|██████████| 25/25 [00:37<00:00, 1.49s/it, loss=0.0145]\n", + "...\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "train completed, total time: 1676.1360158920288.\n" + ] + } + ], + "source": [ + "max_epochs = 40\n", + "val_interval = max(1, max_epochs // 5)\n", + "use_amp = False\n", + "epoch_loss_list = []\n", + "val_epoch_loss_list = []\n", + "\n", + "scaler = GradScaler()\n", + "total_start = time.time()\n", + "for epoch in range(max_epochs):\n", + " model.train()\n", + " epoch_loss = 0\n", + " progress_bar = tqdm(enumerate(train_loader), total=len(train_loader), ncols=70)\n", + " progress_bar.set_description(f\"Epoch {epoch:02}\")\n", + " for step, batch in progress_bar:\n", + " images = batch[\"image\"].to(device)\n", + " optimizer.zero_grad(set_to_none=True)\n", + "\n", + " with autocast(device_type=\"cuda\", enabled=use_amp):\n", + " # Generate random noise\n", + " noise = torch.randn_like(images).to(device)\n", + "\n", + " # Create timesteps\n", + " timesteps = torch.randint(0, num_train_timesteps, (images.shape[0],), device=images.device).long()\n", + "\n", + " # Get model prediction\n", + " noise_pred = inferer(inputs=images, diffusion_model=model, noise=noise, timesteps=timesteps)\n", + "\n", + " loss = F.mse_loss(noise_pred.float(), noise.float())\n", + "\n", + " if use_amp:\n", + " scaler.scale(loss).backward()\n", + " scaler.step(optimizer)\n", + " scaler.update()\n", + " else:\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " epoch_loss += loss.item()\n", + "\n", + " progress_bar.set_postfix({\"loss\": f\"{epoch_loss / (step + 1):.4f}\"})\n", + " epoch_loss_list.append(epoch_loss / (step + 1))\n", + "\n", + " if (epoch + 1) % val_interval == 0:\n", + " model.eval()\n", + "\n", + " torch.save(model.state_dict(), f\"model_{epoch:04}.pth\")\n", + "\n", + " val_epoch_loss = 0\n", + " for step, batch in enumerate(val_loader):\n", + " images = batch[\"image\"].to(device)\n", + " noise = torch.randn_like(images).to(device)\n", + " with torch.no_grad(), autocast(device_type=\"cuda\", enabled=use_amp):\n", + " timesteps = torch.randint(0, num_train_timesteps, (images.shape[0],), device=images.device).long()\n", + "\n", + " # Get model prediction\n", + " noise_pred = inferer(inputs=images, diffusion_model=model, noise=noise, timesteps=timesteps)\n", + " val_loss = F.mse_loss(noise_pred.float(), noise.float())\n", + "\n", + " val_epoch_loss += val_loss.item()\n", + " progress_bar.set_postfix({\"val_loss\": val_epoch_loss / (step + 1)})\n", + " val_epoch_loss_list.append(val_epoch_loss / (step + 1))\n", + "\n", + " # Sampling image during training\n", + " image = torch.randn((1, 1, 32, 40, 32))\n", + " image = image.to(device)\n", + " scheduler.set_timesteps(num_inference_steps=1000)\n", + " with autocast(device_type=\"cuda\", enabled=use_amp):\n", + " image = inferer.sample(input_noise=image, diffusion_model=model, scheduler=scheduler)\n", + "\n", + " plt.figure(figsize=(2, 2))\n", + " plt.imshow(image[0, 0, :, :, 15].cpu(), vmin=0, vmax=1, cmap=\"gray\")\n", + " plt.tight_layout()\n", + " plt.axis(\"off\")\n", + " plt.show()\n", + "\n", + "total_time = time.time() - total_start\n", + "print(f\"train completed, total time: {total_time}.\")" + ] + }, + { + "cell_type": "markdown", + "id": "3e263b67", + "metadata": {}, + "source": [ + "### Learning curves" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "c7520419", + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAArsAAAILCAYAAADoqVT3AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABpf0lEQVR4nO3dd3xUVf7/8fedkkJCQkmooUm1ANJFsoIKqBQVC+uuICo2bGBHZS2IrCjg/hBdVmn2hoqN9pUoKoKADVEEwQAJvaSRnpn7+2OSIUOSSWcmM6+nDx6ZOffeuZ8cxuGdk3PPNUzTNAUAAAAEIIuvCwAAAABqC2EXAAAAAYuwCwAAgIBF2AUAAEDAIuwCAAAgYBF2AQAAELAIuwAAAAhYhF0AAAAELMIuAAAAAhZhFwBOsQ8//FCdO3dW586dlZyc7OtyACCg2XxdAIDANXbsWG3YsEFdunTRxx9/7Oty/EZ0dLS6dOkiSbLb7T6upmoyMjL08ccf67vvvtMff/yhlJQU5eXlKTIyUq1bt1bPnj01YsQIde3a1delAghyhmmapq+LABCYCLuB6Y033tD/+3//T+np6ZKk0NBQxcbGymq16sCBA8rNzXXve+GFF+qpp55S48aNfVUugCDHyC4AoMIee+wxvfvuu5Kknj176o477lDfvn0VEhIiSTJNUz/99JMWL16slStXavXq1dqxY4feeecdNWrUyJelAwhSzNkFAFTI4sWL3UF33LhxeuuttxQfH+8OupJkGIZ69uypOXPm6JFHHpEk7d692/0YAE41RnYB+LU9e/bo1Vdf1XfffacDBw7I6XQqJiZGffr00ZgxY3TWWWeVeWxSUpJef/11rV+/XklJScrNzVVkZKQ6duyoYcOG6e9//7tstpIfg507d5YkzZ49W23bttUzzzyjLVu2qGHDhkpISJAkXXHFFfrtt9907bXX6rHHHtM333yjV199Vb///rvS09PVsGFD9evXT3fccYfatWvn8foffvihHn74YUnS6tWrFRcXJ0navn27Ro4cKUlasmSJOnfurIULF+rzzz9XcnKynE6nWrdurWHDhmn8+PEeIbNIfn6+3njjDX366adKTEyUxWLRaaedptGjR+uqq67Sm2++qaeeekoNGzbU+vXrK/z3cOzYMf3nP/+RJJ177rl6+OGHZRiG12PGjRunjRs3au3atapXr56ysrJUr149SSemuPTt21evv/56qce/8MILmjt3riRp27Zt7vbvv/9e1113nSTp22+/1caNG/Xf//5XiYmJGjFihGw2m95//33Vq1dP69atU1hYWJk1Dh06VLt371Z8fLwWLFjgse2LL77Qhx9+qM2bNys1NVXh4eFq06aNBg0apOuuu05RUVGlvubOnTv1+uuva+PGjdq3b5/y8/MVExOjuLg4XXLJJbrssssUGRnpte8A1BzCLgC/9cknn+iRRx5Rfn6+LBaLWrdurezsbCUnJys5OVlLly7Vvffeq1tuuaXEsWvWrNHdd9+tnJwcGYahmJgYNWnSRAcOHNCmTZu0adMmLVu2TAsWLCgzDGVkZOjmm29Wenq6Wrdu7RFuQkND3Y8XLVqkGTNmKCIiQk2bNpXT6dShQ4f06aef6quvvtJHH32kVq1alfv9Fn/N3NxcjR07Vj///LOaN2+upk2bat++fdq+fbu2b9+uzZs367///a/H8bm5ubrpppu0YcMGSVJ4eLhiY2O1Y8cOTZkyRWvXrtXZZ59d4lwV8c477yg7O1uS9MADD5QbdItMnz5doaGhlT5fRf3444+69957FRERobZt2yoqKkoXXnih3n//fWVlZenrr7/W0KFDSz12y5Yt2r17tyTpsssuc7fn5ubq/vvv16pVqyRJkZGRatWqlQ4ePKhff/1Vv/76q9555x3Nnz/ffaFhkS+++EKTJk1yv2ebNGmiiIgIHT58WBs3btTGjRv12muv6c0331RMTEyt9AkAT0xjAOCXfvzxR02ePFn5+fkaMWKEvvnmG61cuVJff/21vvvuO1166aUyTVOzZs1yj7YWOX78uB544AHl5OTotNNO0+eff65vv/1WK1eu1A8//KD77rtPkrRp0ybNnz+/zBreffddtWzZUl9++aWWLVumd955x73NarVKkn755Rf95z//0ZNPPqnvv/9ey5Yt07p16zRjxgxJrsD8yiuvVOh7tlhOfCQ/99xzyszM1Mcff6yvvvpKK1as0HfffacLLrhAkpSQkKCff/7Z4/j58+e7g+6NN96o9evXa8WKFdqwYYMeeOABrVixQh988IFH/RX1zTffSJI6deqkM844o8LHRUVF1VrQlaR58+Zp9OjRWrdunT777DM98sgj6tOnj5o1ayZJWrlyZZnHLlu2TJJUr149DRkyxN0+ffp0rVq1SmFhYXr66af1/fffa/ny5frxxx/1xhtvqG3btjp8+LBuv/12ZWZmuo/Lz8/XlClTlJ+fr/POO09fffWV1qxZo2XLlmnDhg1asGCBYmNjtWvXLj333HO11CMATkbYBeCXnn32WTkcDvXu3VvPPfecxyhY48aN9dxzz2nAgAGSpDlz5ngcu27dOh0/flySaxSyffv27m02m0233HKL+vTpI+lE4CnNH3/8oeeee06xsbElthWNbG7ZskU33nijx5QIwzB0+eWXq3fv3pJcv3aviOKjpb/++qteeOEFj5HDyMhIj7mvxV/X4XDozTfflCT16dNHDz30kHvE2m6366abbtJtt92m7du3V6iWk23ZskWS1L179yodX1vS09P12GOPeUzpsFgsGj58uCTpyy+/9FgdorgVK1ZIck1lCA8PlyQlJia65yVPmTJFV111lcdUlz59+mj+/Pmy2+3au3ev3n//ffe27du3KyUlRZI0ceJENW3a1L3NMAzFx8friSee0DnnnFPmFAgANY+wC8DvJCcn66effpLkmttZfMSzuGuvvVaStHXrVu3atcvdPmTIEG3ZskXfffed/va3v5V6bNH6r0lJSWXW0bVrV7Vt29ZrrTabTTfeeGOp204//XRJ0oEDB7y+RmkGDx5cYq6vJLVq1co933P//v3u9q1bt+ro0aOSPH8lX9xNN93kDnWVkZGRoby8PElyj5j6i0suuaTUedeXXnqpJCkzM9M9Kl3czz//rL1790qSLr/8cnf7Z599JtM0Vb9+fY0aNarUc7Zq1UqDBg2SdCIwS54/rBw6dKjUYwcPHqxXX31Vjz76qPdvDECNIewC8DubN292P+7YsWOZ+xUfZfztt988tlksFjVu3LjMmzYUXShVFOJKc/J8zNI0a9ZM9evXL3VbUXtOTk65r3OyTp06lbmt6HWLj1ju2LHD/bgoZJ8sMjJSPXv2rHQtxX9VX5WwXJvK+jvq0qWL+71T2lSGohH9pk2bql+/fu72X375RZJ02mmnlRqii3Tr1k2S64cMp9MpSerQoYOaNGkiSXrwwQf1yiuvuAM1AN/hAjUAfufgwYPux8OGDavQMYcPH/Z4npeXpw8//FBffPGF/vzzT6WmplY6dDZs2LDcfbyNdJY1Il0RFXnd4vcEOnbsmPtxUeAqTdu2bbV27dpK1VJ8zm3R9BB/4e3vaOTIkZo9e7YSEhKUl5fnsRZw0YjsyJEjPf6eit57v/zyi3tVDm9ycnJ0/PhxRUVFKSQkRM8//7xuv/12paWlaebMmZo5c6batm2rfv366bzzztPf/va3Wp3DDKAkwi4Av1N01b/kGuGsSGgsPuJ47NgxXX/99R7LVTVt2lRxcXHu0bojR47oyJEjXl/T28hekeoE2pp83eJ9VtqSZEXKGoX2pkGDBu6lw/bs2VPp42uTt7+jESNG6Pnnn9fx48e1du1anX/++ZKkH374wR1qi09hkE6MwkdGRrqXhCtP8RH23r1769NPP9Vrr72mzz//XPv379euXbu0a9cuvfvuu2rQoIHuuOMO99JpAGofYReA34mIiHA/XrhwYakXiHnzzDPPuIPu2LFjdfvtt5e4e1fxNVwDQfGAW1BQUOZ+xackVJRhGDrjjDO0adMm/fDDDzJNs8JLj1VHde9m37JlS/Xs2VM//PCDVqxY4Q67RVMYzjjjjBLTZIree2effXaJdXcrqmnTpnrggQf0wAMP6M8//9R3332nb7/9VuvWrVNqaqqefvpp5eTklLpkHoCax5xdAH6n+K/wi1+EVRH5+fnuOZrx8fGaMmVKqbepLbpqPlBER0e7HxddqFaaqo7MFgXF/fv36+uvv67wcVlZWXr88cc95hQXVzTftTRpaWmVK7IURTfpSEhIUH5+vhwOh/v9UdqFfEXvvapcVFiajh07aty4cXrllVe0evVq9ejRQ5Lrh6309PQaOQcA7wi7APxO0cU/ktzrxpbGNM0So5jHjh1z/yq6aHmxkzmdzlKv0K/Liq8aUdbyYllZWdq4cWOVXv+KK65wL5c1Y8aMMpfzOtns2bP1zjvvaOTIkfrrr7/c7UXzVr0FvqKLxarj4osvlt1uV3p6uvtmIkeOHJHVatWIESNK7F+0Ssdff/1VYh54cd4ubCxrZL1p06buO+fl5eV59AeA2kPYBeB3mjdvrl69ekmS3nzzTWVlZZW638cff6z+/fvrwQcflMPhkHRilQWp7NHbl19+2WPJsYoGN3/WtWtX97q6y5cvL3WfhQsXltmX5WnUqJGeeOIJSa7b4U6cOLHcfps3b577VsBXXnmlTjvtNPe25s2bS3Kta1vaRW/r16/Xr7/+WqVai2vYsKHi4+MlSV9//bX+7//+T5I0YMCAUu9gNmLECBmGIafTWeY0BtM0dcstt+iSSy7R0qVL3e3PPvus+vfvryeffLLMeopfJFmV+dMAKo+wC8Av3XfffbJYLNq3b59uueUW921dJdeo2HvvvafHH39c6enpaty4sfuOYPXr13cvR/XBBx94LEl28OBBPfXUU3rxxRd15513uts3bdp0ir6r2hMeHu5euWL16tV6+eWXlZ+fL8k1tWPBggV66aWXPJbZqqzhw4frpptukuS6WcOll16qzz//3GMesGma2rRpk2699VY9//zzklzTSR577DGP1zrnnHPctU2dOtU9wutwOLRq1SpNnDjRvU91Fa25+80337inYJS1FnGbNm00evRoSdLixYv14osvelz8t3//ft1///1at26ddu3a5bH0Wbt27XTs2DG9//77mjt3bolpGNu2bdO///1vSVL79u09bnYCoPZwgRqAWpeYmFhmuCjummuu0T/+8Q9JUq9evTR9+nT961//0saNGzV06FC1bNlSdrtdBw4ccI+QXXzxxZo4caLH69x777267bbblJGRoSuvvFItWrSQaZo6cOCArFarpk2bpt69e+vFF1+U0+nUbbfdphYtWujVV1/1u5smVMa9996rDRs2KDk5WbNmzdK8efPUtGlTHThwQFlZWbr33nuVl5dX4Tu6leaBBx7QWWedpccee0y7du3SvffeK7vdriZNmshut2vfvn3uX/GHhIToxhtv1J133lliveOhQ4fqzDPP1G+//aaPP/5Yn332maKjo5WVlaWcnBwNGzZMF110kdavXy/JFYIre4vjIhdccIEiIiL0559/SnJdhDZ48OAy93/kkUd05MgRrV69WnPmzNHLL7+sFi1aKDMzU4cPH5bT6VRISIiefvppj7B75ZVX6vvvv9enn36qF154Qf/9738VGxurevXqKSUlxb08XOPGjTVr1qwqfS8AKo+wC6DW5ebm6o8//ih3v5OXAhs1apR69eqlV199VevWrdP+/fvldDoVGxurLl26aNSoUbrgggtKrAwwcOBALVq0SC+//LI2b96sQ4cOKTY2ViNHjtS4ceN05plnSnLdDvaVV17R0aNHFRoa6nXJrrogNjZW77//vubNm6eEhAQdOHBAaWlp6t27t66//noNGDBAL7zwgiRVazWFSy65RH/729/0ySef6Ouvv9a2bdvcITA6Olrt27dXfHy8Ro0aVeaav3a7Xa+++qpeeuklJSQkaO/evcrLy1PHjh01atQo/fOf//S4GURubq7HFJXKCAsL05AhQ9xTDi666CL3lI+y9n/ppZf0xRdf6KOPPtLmzZuVlJSkiIgIdejQQfHx8Ro9enSJO9xZLBbNnDlTF198sT755BNt2bJFR44c0aFDhxQREaEePXrovPPO07XXXutxQSGA2mWY1V3bBQBQZzzzzDNatGiROnfurE8++cTX5QBArWPOLgAEENM0lZGRUeb2oiXAWrRocapKAgCfIuwCQIB47LHH1KNHD1111VWlrl+7f/9+9xzYmrr4CwD8HWEXAAJEnz59lJ2drV27dunhhx/2WHotMTFRd9xxh/Lz89WwYUONGjXKh5UCwKnDnF0ACCBTp07Vm2++Kcl1EViLFi1UUFCgvXv3SnItzfbiiy9WawkyAKhLCLsAEGC++eYbvf322/rzzz918OBBWa1WxcXFacCAARo3bpz7hg4AEAwIuwAAAAhYzNkFAABAwOKmEqU4fLjsZXvKYrEYatQoQseOZcrpZLD8ZPRP+egj7+gf7+gf7+if8tFH3tE/3vmif2Jj61doP0Z2a4jFYsgwDFksVb8rUSCjf8pHH3lH/3hH/3hH/5SPPvKO/vHOn/uHsAsAAICARdgFAABAwCLsAgAAIGARdgEAABCwCLsAAAAIWIRdAAAABCzCLgAAAAIWYRcAAAABi7ALAACAgEXYBQAAQMAi7AIAACBgEXYBAAAQsAi7AAAACFiEXQAAAAQswi4AAAACFmEXAAAAAcvm6wKC3S87jujDr//SwLNb6IKecb4uBwAAlGLq1Me1bNmnFdr3kUce17BhI6t9zvj43jr77J6aO/flar9WMCPs+tiqjUlKOnRc73+5U4N6tJTFMHxdEgAAOMlNN92qG28cp4yMHDkczsK269S2bTtNmfKkx77Nm7eokXPOn/+a6tWrVyOvFcwIuz5mtbrCbW6+Q1k5BYoMt/u4IgAAcLIWLVqoYcMIpaRkqqDA6W4PDQ1Tly5neD3WNE05HA7ZbJWLXeW9LiqGObs+Fh0R4n6cdjzXh5UAAICasGDB/xQf31s//rhJkybdrgsvHKBVq5a7ty9f/pluu+1GDR9+oS68cID++c8r9fLLLykrK9PjdeLje+vOO29xP583b67i43tr165EzZ8/T1deOUIXXHCurrlmlN566zWZpnnKvse6hJFdH4uOCHU/TsvMU8tYHxYDAABqzCuv/FdnndVN119/k+LiWkmS3n//Hf2//zdTAweerxtvvEU2m01r136j115bqD17dmvatBllvp7d7vrt7/PPP6eYmBg9+OCjkqTFi+frpZfmKDq6gYYPv7T2v7E6hrDrYx4ju5l5PqwEAADUpPr1o3THHRM92tLSUnXuuX/T448/rZAQVwbo2bO3Nm/+WWvWJCgrK6vcebphYaH617+mup83aNBQ48eP0fr13xF2S0HY9bHoyOLTGAi7AIC6aeMfh7T0m7+Uk+fwdSmlCguxatTfTlPvLk1O2Tn79x9Qou2mm24rdd/WrVtr69bfdPDgAbVrd5rX173wwqEez1u0aCnJFaRREmHXx4qP7KYzsgsAqKNWfL9b+49m+boMr5Z/v+eUht1GjRqXaDt06KAWLZqvTZs26MiRQ8rPz/fYbprOEsecLCbGc86j1WqVJDmd5R8bjAi7PhblMY2BC9QAAHXTJf3a6CM/H9m9pF/rU3rOk1dfyMnJ0R133KxDhw7qn/+8Tr1791X9+vVlGIbmz5+ntWu/OaX1BQvCro+dfIEaAAB1Ue8uTU7pqGldtGnTBu3fv09XX/0P3XrrHR7bTh7hRc3x66XHlixZouHDh6tr164677zzNHPmTOXllR0Ijx07pieeeEIXXHCBunfvrosuukgvvfSS12N8LTzUKrvN9ddA2AUAIHAVTTNo0KCBR/sff/yuH37YKElyOPxzZLwu89uR3aVLl2rKlCmaPHmyBg8erB07dmjy5MlKS0vTU089VWJ/p9Op2267TSkpKZo2bZpatWqlX3/9VY8++qiOHDmixx57zAffRfkMw1BUvRAdTc/hAjUAAALYWWd1VXh4PX344ftq1aqNGjVqpF9//UUrVy7TVVddo3fffVMrViyT3R6itm3b+brcgOG3I7tz587V8OHDdf311ysuLk6DBg3SxIkTtWTJEu3fv7/E/omJifrll190++2369xzz1WrVq00bNgwXXrppfr004rdy9pXilZkOJ6drwIHk8sBAAhEjRo11jPPzFJsbBNNn/6EHn30AW3fvk0zZ76ga665Vh06dNInn3yoDz54z9elBhS/HNndvXu3kpKSdPfdd3u0Dxo0SE888YTWrl2rq666qtRji65ILGK32/3+6sTi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gMViKCY6TAdTsnU4NUemacowDF+XBQAA4DM1EnYPHDig5cuXa+vWrUpJSZFhGGrcuLHOOussDRs2TA0bNqzS6y5ZskSLFi3Snj171LBhQ1166aW6++67PUaPy5Kamqrhw4crNDRUCQkJVTp/XRTbMFwHU7KVm+9QemaeoiNDfV0SAACAz1Q77C5evFizZs1SQUGBTNP02LZ06VLNmjVLU6dO1YgRIyr1ukuXLtWUKVM0efJkDR48WDt27NDkyZOVlpamp556qtzjp0+frrS0tKBbBcJjRYbUHMIuAAAIatUKu2vWrNEzzzyj8PBwXXbZZerWrZsaNWokp9Opo0eP6scff9SKFSs0efJktW7dWt26davwa8+dO1fDhw93X9gWFxeniRMnaurUqbr99tvVvHnzMo/9+uuvtWrVKl166aVav359db7FOsdzRYYsdYiL9mE1AAAAvlWtpcdef/11RUVF6eOPP9a0adM0evRoDR48WEOHDtU//vEPPffcc3r//fdlt9s1f/78Cr/u7t27lZSUVGK93kGDBsnpdLpXfyjN8ePH9fjjj2vixIleA3GgKn5jCVZkAAAAwa5aI7u//fabRo4cqdatW5e5T5cuXTRixAh9+eWXFX7dxMRESVKrVq082ps1aya73e7eXppZs2YpNjZW48aN04svvljhcxZnsRiyWCp3YZfVavH46ivNG5+4U92RtBzZbL6tp4i/9I8/o4+8o3+8o3+8o3/KRx95R/9458/9U62wm5GRoaZNm5a7X6tWrZSamlrh101PT5ckRUZGerQbhqGIiAj39pNt2rRJH3zwgT744ANZLFXv7EaNIqq8ikFUVHj5O9Wi8IgTc3SPZeSqYUP/uk2zr/unLqCPvKN/vKN/vKN/ykcfeUf/eOeP/VOtsBsVFaXk5ORy99u7d6/q169f4dctL2iWtj03N1ePPvqobrnlFnXs2LHC5yrNsWOZVRrZjYoKV3p6thwOZ7XOX10NIkOUejxP+45kKiUl06e1FPGn/vFX9JF39I939I939E/56CPv6B/vfNE/FR3Qq1bY7d69uz799FONGTNGnTp1KnWfP/74Q5988on69+9f4deNioqS5Bo5Ls40TWVmZio6uuRFVy+88ILCw8N16623VuI7KJ3TacrpNMvfsRQOh1MFBb79nyC2QbhSj+cpPTNPGZl5Cg+tkRXm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i7ALAACAgEXYBQAAQMAi7AIAACBgEXYBAAAQsAi7NWDJkiUaPny4unbtqvPOO08zZ85UXl6er8vyCxdccIE6d+5c4s+IESN8XZpPLV68WGeddZbuueeeEtt++uknXXvttTr77LPVp08fTZo0SQcPHvRBlb5TVv9Mnjy51PdT586ddezYMR9Ve+p9+OGHuuyyy3T22Wdr0KBBevTRR3X06FH39p07d+rmm29Wz5491aNHD910003auXOnDys+tbz1zwsvvFDme+jXX3/1ceW1z+FwaP78+brkkkvUvXt3DRw4UA8++KD279/v3ieYP4PK6x8+gzzdeOON6ty5s5KTk91tfvn+MVEtH330kdm5c2dz0aJFZlJSkvnll1+a/fr1M6dMmeLr0vzC+eefbz7zzDPmoUOHPP4cO3bM16X5REpKinnrrbea8fHxZs+ePc1JkyZ5bN+5c6fZvXt388EHHzR37txpbt682bzyyivN4cOHm3l5eT6q+tQpr38eeugh8+9//3uJ99OhQ4dMp9Ppo6pPrUWLFpmnn366+eqrr5q7d+82v/nmG3PQoEHmNddcYzqdTvPo0aPmueeea44fP97cunWruW3bNvPmm282BwwYYKakpPi6/FpXXv/MmTPHPO+880p9D+Xn5/u6/Fo3bdo08+yzzzaXLl1q7tmzx/z222/NCy+80LzkkkvMvLy8oP8MKq9/+Aw64f333zfPPPNMs1OnTmZSUpJpmv77bxhht5ouvPBC89577/Voe+utt8wuXbqY+/bt81FV/uP8888358yZ4+sy/Mbrr79ujh071jxy5Ih5/vnnlwhzkydPNgcNGuTxj+6OHTvMTp06mZ988smpLveUK69/HnroIXPMmDE+qs73nE6nOWDAAHPy5Mke7e+//77ZqVMnMzEx0XzhhRfM7t27m2lpae7tqampZrdu3cz//ve/p7rkU6oi/TNnzhzz/PPP91GFvpWXl2cOHDjQnDt3rkf70qVLzU6dOplbtmwJ6s+givRPsH8GFTl48KDZu3dv86mnnvIIu/76/mEaQzXs3r1bSUlJGjhwoEf7oEGD5HQ6tXbtWh9VBn81cOBALVq0SI0bNy51+9q1azVgwADZbDZ3W/v27dWqVSt98803p6pMnymvf4KdYRj67LPP9PDDD3u0x8bGSpIOHTqktWvXqkePHoqKinJvj46O1tlnnx3w76GK9E8ws9vt+uqrr3THHXeUaJckq9Ua1J9BFekfuEydOlW9evXSkCFDPNr99f1D2K2GxMRESVKrVq082ps1aya73e7eDhRp1apVmR+YWVlZOnjwYIn3kyS1bt06KN5P3voHLg0aNPAIspK0evVqhYaG6vTTT1diYmJQv4fK6x+c4HQ69fvvv2vu3LkaNGiQWrduHfSfQcWd3D9dunTxdUl+Yfny5Vq/fr2efPJJj3Z//jeMsFsN6enpkqTIyEiPdsMwFBER4d4e7H777TeNHz9e8fHxuuiii/Svf/1LR44c8XVZficjI0NSyfdTURvvJ5djx47poYce0gUXXKCBAwfqtttu09atW31dls8kJCTovffe06233qr69esrIyNDERERJfYL1vfQyf0jSTk5OZo6daqGDh2q+Ph4XX/99Vq/fr2PKz21nnvuOXXr1k1XXnmlzjnnHL344ot8BhVTWv8UCebPoNTUVE2bNk0PPvigmjZt6rHNn98/hN1qMAyjWtuDQcOGDZWSkqKrr75a8+fP15133qlvvvlG1113nXJycnxdHuqYyMhI5efnq1u3bpo7d66mT5+u9PR0XXPNNUG12kCR5cuX6+6779bw4cM1YcIESXzuFFda/9SrV0+hoaFq2rSpZs2apeeff1716tXTDTfcEFSBd/z48frggw/073//W19++WWJX90Hu9L6x+FwBP1n0PTp09W+fXuNHj3a16VUiq38XVCWol+VFf00U8Q0TWVmZio6OtoXZfmVDz74wON5ly5dFBsbq3HjxikhIUHDhg3zUWX+p6z3U1FbgwYNTnFF/mfKlCkl2rp166aBAwfq9ddf1xNPPHHqi/KR119/XdOnT9c///lPPfroo7JYXGMXUVFROn78eIn9g+09VFb/jB8/XuPHj/fYt0ePHrrkkku0YMECnXPOOb4o95Rr1KiRGjVqpM6dO6t169b6xz/+oe+++04Sn0FS6f2zcuXKoP4M+vrrr/XFF1/o448/LnW7P/8bRtithvbt20uS9uzZo549e7rbk5OTlZ+f794OT507d5Ykj3X5IIWHh6tly5bavXt3iW27du0Kmn+EK6t+/fpq2bKlkpKSfF3KKfP222/r6aef1v3336+bbrrJY1v79u3LfA+ddtppp6pEn/LWP6Wx2Wxq3769du3aVfvF+dCxY8f07bffqm/fvmrWrJm7vWgu8/79+4P6M6i8/inr/REsn0HLly9XVlaWLrroInebaZqSpKFDh6pPnz5++/5hGkM1xMXFqUOHDkpISPBoT0hIkN1uV3x8vI8q8w87d+7U5MmTS0xKL1q4PS4uzhdl+bWBAwfq22+/VX5+vrvtjz/+0L59+3TBBRf4sDLfy8vL0+OPP64vvvjCoz01NVVJSUmlXhQRiNatW6epU6fq0UcfLTXIDRw4UD///LNSUlLcbUePHtXPP/8cFO+h8vrnueee03vvvefRlpeXp23btgX8e6igoEAPPvigli5d6tG+fft2Sa7P5GD+DCqvf5o3bx7Un0GTJk3SJ598oqVLl7r/TJs2TZL08ssva9q0aX77/mFkt5omTZqku+66SwsXLtRFF12krVu3au7cuRo7dqxiYmJ8XZ5PtWjRQt9//722bdumyZMnq2XLltq6dauefvppdejQQYMHD/Z1iadcamqq+0PA4XAoNzdXhw8fluQaHbjpppv06aef6pFHHtHtt9+ujIwM/etf/1K3bt104YUX+rL0U6K8/klJSdGjjz6qvLw8devWTQcOHNDzzz8vwzA0duxYX5Z+Spimqaeeekq9e/fWxRdf7O6bIvXq1dM111yjN998U/fff78efPBBmaapZ555Rk2aNNHVV1/to8pPjYr0j9Pp1LRp0+RwOBQfH6/U1FT973//08GDB/XMM8/4qPJTo0mTJho1apT+97//KTY2Vn379lVycrKmT5+uuLg4XXjhherVq1fQfgaV1z9Dhw7Vl19+GbSfQU2bNi1xUVrRD9Vt27ZVXFyc3/4bZphFY9Coss8++0zz5s3Trl27FBMTo6uuukoTJkxgCSW5pirMmTNH3333ndLT09W8eXMNGjRIEyZMCKr5X0XGjh2rDRs2lLrt3//+t6644gpt2bJFM2bM0ObNmxUaGqoLLrhADz74oBo1anSKqz31yuufYcOG6cUXX9SKFSt08OBBNWzYUN27d9fEiRODYtrQ3r17vY6O3Hnnnbrrrru0Z88eTZ8+Xd9//70Mw1D//v318MMPB/xvUyrSP3fccYfmz5+vpUuXau/evYqMjNTpp5+uu+66S927dz+F1fpGXl6eFixYoI8//lj79+9XgwYN1Lt3b917771q2bKlJAX1Z1B5/ZOTkxPUn0En+/7773Xddddp9erV7s8Xf3z/EHYBAAAQsJizCwAAgIBF2AUAAEDAIuwCAAAgYBF2AQAAELAIuwAAAAhYhF0AAAAELMIuAAAAAhZhFwDg1dixY9W5c2f3rb4BoC7hdsEAUEuSk5MrdYvMojugAQBqDmEXAGpZeHh4hUJsjx49TkE1ABBcCLsAUMtCQ0M1fvx4X5cBAEGJsAsAfuaee+7RsmXL9PHHH+uvv/7SggUL9Ndff0mSzjrrLN19993q06dPieO++OILvfnmm/r999+VmZmpBg0a6Oyzz9aNN96onj17lth/z549eumll7R27VqlpqaqadOmOuecczRhwgS1bNmy1NrWr1+vF154QVu3blVoaKhOP/103XfffTrzzDM99vvpp580f/58/fLLL0pJSVFkZKRatWqlkSNHasyYMbJarTXQUwBQPsIuAPiZkJAQSdJ7772nTz/9VMOHD9fgwYO1bds2rVixQjfccIMWL16s3r17u4+ZM2eOXnzxRTVo0EAjRoxQbGys9uzZo88++0wJCQmaOXOmhg0b5t5/69atuu6665STk6NLL71UcXFx2rFjhz744AOtXr1ab7/9ttq2betR17p167RgwQINHTpUAwYM0M8//6w1a9bop59+0vLly9WsWTNJ0qZNmzRu3DiFhYXpkksuUcuWLZWZmakvv/xS06dP1y+//KLZs2fXfkcCgCSZAIBakZSUZHbq1Mns27dvpY576KGHzE6dOpndu3c3d+7c6bHtf//7n9mpUyfz2muvdbf99ttvZufOnc1+/fqZ+/bt89h/48aNZufOnc0+ffqYWVlZ7vZRo0aZnTp1Mr/55huP/d944w2zU6dO5m233eZuGzNmjNmpUyfznHPOMRMTEz32v/nmm81OnTqZixYtcrfde++9ZqdOncyvvvrKY9+8vDxzzJgxZq9evUrUCQC1hZFdAKhlpmkqOTnZ6z52u11Nmzb1aBsxYoROO+00j7Zrr71Wc+bM0aZNm5SRkaH69etr6dKlMk1T//jHP9S8eXOP/Xv37q1zzjlH69at05o1a3TxxRdr27Zt+u2339SpUyfFx8d77H/llVdq7969atKkSYkaR48eXWK099xzz9WaNWu0e/dud1t6erokqV69eiW+x0WLFslm458eAKcOnzgAUMvS0tLKXYKsS5cu+vjjjz3aevXqVWK/iIgItW7dWjt37lRiYqK6deumLVu2SFKp83IlqVu3blq3bp22bt2qiy++WJs3b5YknX766SX2DQsL04MPPljq65w8L1eS6tevL0nKyclxtw0aNEhff/217rjjDt188806//zz1aFDB0ki6AI45fjUAYBaFhERoWeffdbrPpGRkSXaGjduXOq+0dHRkk6MoB49elSSFBMTU+r+jRo1kiSlpKRIko4dO+bxOhVV2v6GYUhyjV4X+ec//6kjR45o4cKFmjlzpmbOnKnY2FgNGDBAl19+ufr371+p8wJAdRB2AaCW2e12DR48uNLHlTUKWhQsLRbXTTBLC5zFOZ1Oj/1Ofp2aZhiGJk6cqBtuuEFr1qzR2rVrtW7dOi1dulRLly7V6NGj9dRTT9XKuQHgZNwuGAD8VNEI7MlSU1MlnRhpLRrRPXz4cKn7F438Fo0UF430FrXXlqioKI0cOVLPPPOM1qxZo8WLF6tZs2Z67733tH79+lo9NwAUIewCgJ/65ZdfSrRlZmYqOTlZNptN7dq1kyR17dpVkvTjjz+W+jo//fSTx37dunVzv/7Jo7tOp1OTJk3SxIkTVVBQUKW609LStHfv3hLt/fv31w033CBJ7nnGAFDbCLsA4Kc++ugjJSUlebS9+eabys/P14ABA9yrHVxxxRWyWCx69913deDAAY/9v/76a/3www9q2rSpe+WFzp0768wzz9TevXv14Ycfeuy/bNkyLV++XMePH6/SxWQZGRkaOHCgbrjhBqWlpZXY/scff0iSe01eAKhtzNkFgFqWm5urBQsWlLtfaGioxowZ435+/vnn68orr9TIkSPVpEkTbd26VStWrFBYWJjuuece934dO3bU3Xffrf/85z+6/PLLNXLkSMXExOjPP//U8uXLFRYWphkzZshut7uPefrppzV27FhNmTJF3333nTp06KCdO3dq+fLlatCggR577LEqfa/169fXrbfeqv/85z/um2E0a9ZM2dnZ+vHHH7VhwwadeeaZGjp0aJVeHwAqi7ALALUsOzu73NUYJFdQLB52r7rqKg0aNEgLFy7Uzp07ZbFY1L9/f91zzz0llg2bMGGCOnbsqDfeeENLly5Vdna2GjVqpGHDhunWW291L/1V5PTTT9cHH3zgvl3wypUr1axZM1122WW688471aJFiyp/vxMmTFC7du20ZMkSJSQk6NixY7LZbGrTpo3uvvtuXX/99e67xAFAbTPM2rocFwBQJZMnT9ZHH32k1157Tf369fN1OQBQpzFnFwAAAAGLsAsAAICARdgFAABAwCLsAgAAIGBxgRoAAAACFiO7AAAACFiEXQAAAAQswi4AAAACFmEXAAAAAYuwCwAAgIBF2AUAAEDAIuwCAAAgYBF2AQAAELAIuwAAAAhY/x/BhVex7M7+TAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.style.use(\"seaborn-v0_8\")\n", + "plt.title(\"Learning Curves\", fontsize=20)\n", + "plt.plot(np.linspace(1, max_epochs, max_epochs), epoch_loss_list, color=\"C0\", linewidth=2.0, label=\"Train\")\n", + "plt.plot(\n", + " np.linspace(val_interval, max_epochs, int(max_epochs / val_interval)),\n", + " val_epoch_loss_list,\n", + " color=\"C1\",\n", + " linewidth=2.0,\n", + " label=\"Validation\",\n", + ")\n", + "plt.yticks(fontsize=12)\n", + "plt.xticks(fontsize=12)\n", + "plt.xlabel(\"Epochs\", fontsize=16)\n", + "plt.ylabel(\"Loss\", fontsize=16)\n", + "plt.legend(prop={\"size\": 14})\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "38724c9b", + "metadata": {}, + "source": [ + "## Sampling Brain Image\n", + "\n", + "In order to sample the brain images, we need to pass the model an image containing just noise and use it to remove the noise of the image iteratively. For that, we will use the `.sample()` function of the `inferer`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "092eb6a0", + "metadata": { + "lines_to_next_cell": 2 + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 0%| | 0/1000 [00:00" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.style.use(\"default\")\n", + "plotting_image_0 = np.concatenate([image[0, 0, :, :, 15].cpu(), np.flipud(image[0, 0, :, 20, :].cpu().T)], axis=1)\n", + "plotting_image_1 = np.concatenate([np.flipud(image[0, 0, 15, :, :].cpu().T), np.zeros((32, 32))], axis=1)\n", + "plt.imshow(np.concatenate([plotting_image_0, plotting_image_1], axis=0), vmin=0, vmax=1, cmap=\"gray\")\n", + "plt.tight_layout()\n", + "plt.axis(\"off\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "f0acc27a", + "metadata": {}, + "source": [ + "### Sampling with Denoising Diffusion Implicit Model Scheduler\n", + "\n", + "Recent papers have proposed different ways to improve the sampling speed by using fewer steps in the denoising process. In this example, we are using a `DDIMScheduler` (from [Song et al. \"Denoising Diffusion Implicit Models\"](https://arxiv.org/abs/2010.02502)) to reduce the original number of steps from 1000 to 250." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "e3e43b95", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 250/250 [00:07<00:00, 32.79it/s]\n" + ] + } + ], + "source": [ + "scheduler_ddim = DDIMScheduler(\n", + " num_train_timesteps=num_train_timesteps,\n", + " schedule=\"scaled_linear_beta\",\n", + " beta_start=0.0005,\n", + " beta_end=0.0195,\n", + " clip_sample=False,\n", + ")\n", + "\n", + "scheduler_ddim.set_timesteps(num_inference_steps=250)\n", + "\n", + "model.eval()\n", + "noise = torch.randn((1, 1, 32, 40, 32))\n", + "noise = noise.to(device)\n", + "\n", + "image = inferer.sample(input_noise=noise, diffusion_model=model, scheduler=scheduler_ddim)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "89f93ab8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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7N271827d+8ue0aOHOnm0RKKaJmPuoW7b98+2RO55ppr3PzNN9/M0tfLil69ern5iBEjZI+6wWymbxCr5R5mZkuWLHHz6L0XTR9UqVLFzVetWiV7duzYIWtK9N579913M/311AIsM7M9e/Zk+uup5TtmenlR9DOtJnOiiZ3p06fLWlZk5GjmN3AAABLEAQ4AQII4wAEASBAHOAAACeIABwAgQRzgAAAkKMNjZNHISaVKldw8uqb/66+/unk02vXTTz/JWt68ed28du3asica87n//vvdPHfu3LLn1VdfdfOKFSvKnrlz58qaGgn76KOPZM8FF1wgaxs3bnTzZcuWyR417pGVUQ8zvSRjxYoVsicae8nK42vVqpWbf/XVV7LnjDPOkLXo+VP69u0ra5999pmbb9iwIdPfJ1qWMHv27Ex/PQD/GYyRAQBwkuIABwAgQRzgAAAkiAMcAIAEcYADAJAgDnAAABKU80R8EbU9KStjL1l17NgxN2/QoIHsicbIpk6d6ubRGNnWrVvdPBp/izaLLVq0SNaUCRMmyNrvf/97N4/GoAYNGuTmN910U+Ye2H850Rt71LjYSy+9JHvUCFf0Whw6dChzD8ziTWAzZsyQtaz83KgNcPny5cv01wKQBn4DBwAgQRzgAAAkiAMcAIAEcYADAJAgDnAAABJ0Qm6hR7esld/97nduHt3Ojahb6FWrVs3S17vooovc/NFHH83016pcubKsVa9eXdbUEpShQ4fKnpIlS8pa48aN3Xz48OGyR9U6dOgge7Zs2SJrCxcudPNoWkD1mOnXKVqOomzbtk3W9u3bJ2vnnXeem3/44YeZfgxmenFKrly5ZI+aWFCTEQDSx2/gAAAkiAMcAIAEcYADAJAgDnAAABLEAQ4AQII4wAEASFC233777beM/MF+/frJ2oABA9z81ltvlT1Dhgxx83POOUf2rFq1StbU0oZojCZ//vyytnv3bje//PLLZc8777wja0o0jlW4cGE3//nnn2VP9HKqr7dp0ybZc+TIETc///zzZc+oUaNkbf369W4eLYlRjyFyzz33yNro0aPdvFChQrJn+fLlsnbFFVe4eTRGdvjwYVlr2rSpm0fjiO+++66sKa1atZI19bORlRFBAJmXkaOZ38ABAEgQBzgAAAniAAcAIEEc4AAAJIgDHACABGX4Fnq2bNlkTd2kXrly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aPlOtPBlyZIlbq5up5uZValSxc2vvfZa2ZOVm+bRrXYWnQAnDrfQAQA4SXGAAwCQIA5wAAASxAEOAECCOMABAEgQBzgAAAnKmeE/mFP/0ZIlS7p5tCzkggsucPONGzfKHrXcw8ysTZs2bq4WeJiZjRgxQtZ+//vfu/no0aNljxqjiRaqNGzYUNYWLVrk5mrBiJnZvn37ZO3QoUNunjdvXtnz+uuvu7l6/czMFi9eLGtqIU2xYsVkT+HChWXthx9+cPMNGzbInoEDB7p50aJFZU/0+IoXL+7ml112mew55ZRTZE2Ni9WvX1/2dO7c2c2vuuoq2ROpU6eOm6sRNwD/efwGDgBAgjjAAQBIEAc4AAAJ4gAHACBBHOAAACSIAxwAgARleBtZNPayd+9eN4+2SFWqVMnN//jHP8qeaFvU/Pnz3fzAgQOy55577pG1zz77zM3Xr18ve9QIXLQZKxpdKl26tJtXrVpV9kQbq8qUKePm0ciV2rB28OBB2RONGqnxpNq1a8ueadOmZfrrqZE5M/08RFvUGjduLGvLli1z86+++kr23HbbbbI2depUN482111++eVunidPHtmzYMECWVPvieuvv172vPzyy7IGIHPYRgYAwEmKAxwAgARxgAMAkCAOcAAAEsQBDgBAgjK8zEQt9zAze+2119w8ujU7aNAgN1c3r83MChUqJGvqpnKFChVkT3Rb+ssvv3Tz/fv3y57evXu7ebTco169erL2+OOPu7m6cWxmVrlyZVm777773LxBgwayRz1/Xbp0kT3RwpfWrVu7+c6dO2VP9uz635lbt25187Vr18oeNRUQ3YSPlvmo6YPotYhu/qv3slpYYmZ2++23u3n03L333nuypowZMybTPQD+PfgNHACABHGAAwCQIA5wAAASxAEOAECCOMABAEgQBzgAAAnK8BjZkCFDMv3F69evL2vHjx9383nz5smeuXPnypoa8+nRo4fsufvuu2VNLVWJFrTMmTPHzRs1aiR7XnjhBVlTSzcmTJgge9Tzamb27LPPunm0LET9fdWyF7N4Kchpp53m5mohjplZ8+bNZU2Nfg0bNkz25MqVy82jhT3RYhI1qvXxxx/LnurVq8uaGh8sW7as7FGLD959913Z07JlS1krV66cm48aNUr2APjP4jdwAAASxAEOAECCOMABAEgQBzgAAAniAAcAIEEc4AAAJCjDY2TRKFTu3LndvGrVqrJHjcq89NJLsmfRokWytn79ejfPkSOH7KlYsaKsFSlSxM2jMRo1sjZz5kzZs2vXLlnbsWOHm0cbzMqXLy9r69atc/NoY9XUqVPdvEOHDrKnadOmsjZ//nw3//7772XPq6++KmsjR4508yNHjsge9X6Nxumi7Wtqg16vXr1kT7QJb8uWLW5+9dVXyx618a5OnTqyp0WLFrKmqG1yZnqDH4B/D34DBwAgQRzgAAAkiAMcAIAEcYADAJAgDnAAABKU7Te1BeH/ULduXVl78skn3TxavrBq1So3P/PMM2XPyy+/LGt33nmnm0+cOFH2qKUWZnohR9RTrFgxN9+6davs2bNnj6yp5RoHDhyQPfv375e1nj17uvmDDz4oex544IFM92zfvl3Wpk+f7uY//fST7FmzZo2sbdq0yc1nz54tey6++GI3z5s3r+xZvny5rD3zzDNuPmDAANkTPUc1a9Z0c7Wwx8xs4cKFbj506FDZs3nzZlnbuXOnm7/xxhuyp3fv3rIGIHMycjTzGzgAAAniAAcAIEEc4AAAJIgDHACABHGAAwCQIA5wAAASlOExsmuvvVbW1LhTq1atZI9aatG/f3/Zc+utt8pa8+bN3Xzp0qWyp0qVKrK2ceNGN3/ooYdkT758+WRNmTNnjqypxS5vvvmm7Dl27JisqTGkaCxNjSHddNNNsida4nHaaae5ebRYpnLlyrK2cuVKN4/er2pJzNixY2XPvn37ZK1bt25uHi2+Wb16taz96U9/cnO1uMVML9+JRjlPPfVUWVOjdpMmTZI97du3lzUAmcMYGQAAJykOcAAAEsQBDgBAgjjAAQBIEAc4AAAJyvAtdLXcw8ysU6dObn7NNdfIngYNGri5uiFsZjZ8+HBZ69ixo5sfP35c9kSLU9QCknXr1smeyy67zM2jRRjR3+nSSy9188WLF8ueaKGEWrpRoUIF2aPeHtFijQULFmS6VrJkSdmjlrCYmX3zzTduvn79etlTr149N7/hhhtkTzRhoCYqomUm0U19daO8cOHCsmf37t1uPnjwYNkzefJkWWvUqJGbRxMLy5YtkzUAmcMtdAAATlIc4AAAJIgDHACABHGAAwCQIA5wAAASxAEOAECC9CxQJnz99ddufvnll8ueqVOnunm1atVkTzRGo5ZhVKpUSfbMmjVL1goVKuTmrVu3lj1Llixx8+3bt8ueJ554Qtb69Onj5h988IHsWbhwoazt37/fzaMxsgIFCrj56NGjZU/BggVlrVatWm5+3333yZ41a9bI2i+//OLmd955p+wZN26cm6v3sZnZW2+9JWtqaU+XLl1kT44cOWStbdu2bq5GG83M1q5d6+YHDx6UPWeddZaszZ07182PHj0qewD8Z/EbOAAACeIABwAgQRzgAAAkiAMcAIAEcYADAJAgDnAAABKU4W1kF198saxt3rzZzXPlyiV7XnzxRTdX26XMzD755BNZe/nll9082pCUPbv+98vevXvdvE2bNrJHjexMmzZN9kTP0cyZM928WbNmske9FlGtSpUqsmfOnDluXrVqVdnTsGFDWVNbs1RuFo8uqU1vq1atkj07d+5080OHDsmeaCTy+eefd/PGjRvLnvz588ta7ty53Tzaaqe2+xUvXlz2fPHFF7Km3pdLly6VPQBOHLaRAQBwkuIABwAgQRzgAAAkiAMcAIAEcYADAJCgDN9Cz5Yt27/7sfxT0QKNlStXuvlVV10leypXrixrajnE1VdfLXvUgoropnmJEiVkTd0svvLKK2WPuj1vZrZ69Wo3P378uOxRN5XVwg0zsyuuuELWWrRo4eYTJkyQPWeccYasHTt2zM3r1q0re95//31ZU7p37y5r6jlSt9PNzF599VVZU0tsBg4cKHvUDXr1mpuZFStWTNYaNWrk5s2bN5c9AwYMkDUAmcMtdAAATlIc4AAAJIgDHACABHGAAwCQIA5wAAASxAEOAECCcmb0D3bo0EHWpkyZ4ubRwosff/zRzfft2yd7brjhBllTfdFiDbUsxMysUKFCbh6NE5UvX97N582bJ3t27dola5deeqmbr1mzRvYsXLhQ1q6//no379y5s+y55ZZb3HzFihWyp3379rK2ZcsWN48Wf7Ru3VrWhg0b5uYtW7aUPXnz5nXzESNGyB71fjAz27Fjh5v36tVL9pQsWVLWFixY4OZLliyRPepnrVu3brInGs9Ty2Cixw3gP4vfwAEASBAHOAAACeIABwAgQRzgAAAkiAMcAIAEcYADAJCgf+s2snLlysnaaaed5ubTp0+XPY8++qis1ahRI+MP7L9Eo0GtWrVy888//1z2ZM/u/3uoYsWKsueZZ56RtTJlyrh5tAksev4KFCjg5l27dpU9agTuww8/lD3vvfeerBUsWNDNf/nlF9lTqlQpWatQoYKb//TTT7KnSZMmbn7JJZfInui9t3v3bjevVq2a7NmwYYOsqfHBqOfss8928/nz58ued955R9aUCy+8UNbGjRuX6a8HwMc2MgAATlIc4AAAJIgDHACABHGAAwCQIA5wAAASlOFb6HfffbesqRvEOXPqXSkvvfSSmxcpUkT2RDeLH3/8cTfv16+f7In+TmqZQ3QbWS3keOihh2SPukVtZjZr1iw3j5bERI/vueeec3O13MPMrG7dum4eLQv5n6BTp06ypm73R+8vddPczGzv3r1uvnr1atlz/PhxWVOLedRiGTOzoUOHytqJVLZsWVnbvHnzf+QxAP9/wC10AABOUhzgAAAkiAMcAIAEcYADAJAgDnAAABLEAQ4AQIL+rctM8uTJI2uHDx928/r168ueRYsWydqAAQPcPFo+ctNNN8maGgEaP3687Bk0aJCb79mzR/asX79e1nLkyOHmpUuXlj1qWYiZ2Y8//ujmDzzwgOwpXLiwmx86dEj21KlTR9bUaOHYsWNlT1Zk5X0ULR9p2LChrI0ZM8bNq1SpInui5TvqPRaN+0Wvh9KsWTNZmzNnjpuff/75smfixImZfgwAfIyRAQBwkuIABwAgQRzgAAAkiAMcAIAEcYADAJCgDN9Cj5YYqCUQWbkZe8MNN8jaggULZO3YsWNuvnDhQtmjblibmbVr187N77//ftmzc+dONy9atKjsGTlypKwVKFDAzZ944gnZ07t3b1mrXbu2m0e3+9W0gLp5/c+o91HlypVlj1oWYmbWo0cPN48e32mnnebm0furSZMmslarVi0379+/v+y55557ZE0t0vn4449lj5o+UIuGzMyKFy8ua2qCZNu2bbJH/QwCyDxuoQMAcJLiAAcAIEEc4AAAJIgDHACABHGAAwCQIA5wAAASlOExsmiM5ttvv3XzYsWKyZ5du3a5+SOPPCJ71MISM7OmTZu6+dy5c2VPpGTJkm5epEgR2XPzzTe7+eDBg2VP7ty5ZW3SpElu/uc//1n2vPjii7LWqlUrNy9fvrzsGTFihKwp6rkzM9u+fXumv1407nfw4EE3P3r0aKa/T6lSpWQt+nq7d+928yuuuEL2jB49OuMP7N/knHPOkbVNmza5ebR8B8CJwxgZAAAnKQ5wAAASxAEOAECCOMABAEgQBzgAAAniAAcAIEE5M/oHq1SpImtqjEyNikWiUbHs2fW/N5o1a+bmjRo1kj1r1qyRtYYNG7r5vn37ZM+UKVPcPBq96du3r6wNGzbMzdX2q3+mRIkSbv7JJ59k+mvVr19f1mrUqCFr7777rptHG9uyZcsma2pTmXo/mJnlzOm/7dXmNbP4OVejgBs2bJA9WZEjRw5Zq1ChgptHW96WLl0qa3nz5s3w4wLw/wa/gQMAkCAOcAAAEsQBDgBAgjjAAQBIEAc4AAAJyvAyk7p168pa1apV3XzBggWyZ+PGjW4eLa5o3ry5rKnFHxF1K9tM33zOyjKOrGrQoIGbL1y48IR+nw4dOsja+PHj3Tx67nbs2CFraipg5cqVsuess86StcmTJ7t5nTp1ZI+6Ha6WvZiZLVu2TNbWrl0ra0q08KVatWpuPnPmTNmj/r5LliyRPVdddZWsjR071s2jKQwAJw7LTAAAOElxgAMAkCAOcAAAEsQBDgBAgjjAAQBIEAc4AAAJyvAYGQAA+J+D38ABAEgQBzgAAAniAAcAIEEc4AAAJIgDHACABHGAAwCQIA5wAAASxAEOAECCOMABAEjQ/wLU4iSfOdErLwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.style.use(\"default\")\n", + "plotting_image_0 = np.concatenate([image[0, 0, :, :, 15].cpu(), np.flipud(image[0, 0, :, 20, :].cpu().T)], axis=1)\n", + "plotting_image_1 = np.concatenate([np.flipud(image[0, 0, 15, :, :].cpu().T), np.zeros((32, 32))], axis=1)\n", + "plt.imshow(np.concatenate([plotting_image_0, plotting_image_1], axis=0), vmin=0, vmax=1, cmap=\"gray\")\n", + "plt.tight_layout()\n", + "plt.axis(\"off\")\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "b39a47bb", + "metadata": {}, + "source": [ + "### Cleanup data directory\n", + "\n", + "Remove directory if a temporary was used." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "957a45ff", + "metadata": {}, + "outputs": [], + "source": [ + "if directory is None:\n", + " shutil.rmtree(root_dir)" + ] + } + ], + "metadata": { + "jupytext": { + "formats": "py:percent,ipynb" + }, + "kernelspec": { + "display_name": "monai", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/generation/README.md b/generation/README.md index 351416fd1..f2932f6b8 100644 --- a/generation/README.md +++ b/generation/README.md @@ -49,6 +49,9 @@ Examples show how to train Vector Quantized Variation Autoencoder on [2D](./2d_v ## [Training a 2D Denoising Diffusion Probabilistic Model](./2d_ddpm/2d_ddpm_tutorial.ipynb): Example shows how to easily train a DDPM on medical data (MedNIST). +## [Training a 3D Denoising Diffusion Probabilistic Model](./3d_ddpm/3d_ddpm_tutorial.ipynb): +Example shows how to easily train a DDPM on medical data (Decathlon Task 01). + ## [Comparing different noise schedulers](./2d_ddpm/2d_ddpm_compare_schedulers.ipynb): Example compares the performance of different noise schedulers. This shows how to sample a diffusion model using the DDPM, DDIM, and PNDM schedulers and how different numbers of timesteps affect the quality of the samples.