diff --git a/notebooks/MICCAI23_tutorial.ipynb b/notebooks/MICCAI23_tutorial.ipynb
new file mode 100644
index 0000000..0df826e
--- /dev/null
+++ b/notebooks/MICCAI23_tutorial.ipynb
@@ -0,0 +1,1472 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "provenance": [],
+ "gpuType": "V100",
+ "collapsed_sections": [
+ "xshLGkbfBcgi",
+ "SY-KhiXn860d"
+ ],
+ "include_colab_link": true
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ },
+ "language_info": {
+ "name": "python"
+ },
+ "widgets": {
+ "application/vnd.jupyter.widget-state+json": {
+ "717d4dacb81a4529b7e475d1b217568b": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_name": "DropdownModel",
+ "model_module_version": "1.5.0",
+ "state": {
+ "_dom_classes": [],
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "1.5.0",
+ "_model_name": "DropdownModel",
+ "_options_labels": [
+ "gc_lunglobes",
+ "lungmask",
+ "nnunet_pancreas",
+ "totalsegmentator",
+ "platipy",
+ "casust",
+ "nnunet_segthor",
+ "nnunet_liver",
+ "gc_picai_baseline"
+ ],
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/controls",
+ "_view_module_version": "1.5.0",
+ "_view_name": "DropdownView",
+ "description": "",
+ "description_tooltip": null,
+ "disabled": false,
+ "index": 1,
+ "layout": "IPY_MODEL_815a58f1a77740759d70aafe8c929d38",
+ "style": "IPY_MODEL_abba39fb52344edd86567aa053860b3a"
+ }
+ },
+ "815a58f1a77740759d70aafe8c929d38": {
+ "model_module": "@jupyter-widgets/base",
+ "model_name": "LayoutModel",
+ "model_module_version": "1.2.0",
+ "state": {
+ "_model_module": "@jupyter-widgets/base",
+ "_model_module_version": "1.2.0",
+ "_model_name": "LayoutModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "1.2.0",
+ "_view_name": "LayoutView",
+ "align_content": null,
+ "align_items": null,
+ "align_self": null,
+ "border": null,
+ "bottom": null,
+ "display": null,
+ "flex": null,
+ "flex_flow": null,
+ "grid_area": null,
+ "grid_auto_columns": null,
+ "grid_auto_flow": null,
+ "grid_auto_rows": null,
+ "grid_column": null,
+ "grid_gap": null,
+ "grid_row": null,
+ "grid_template_areas": null,
+ "grid_template_columns": null,
+ "grid_template_rows": null,
+ "height": null,
+ "justify_content": null,
+ "justify_items": null,
+ "left": null,
+ "margin": null,
+ "max_height": null,
+ "max_width": null,
+ "min_height": null,
+ "min_width": null,
+ "object_fit": null,
+ "object_position": null,
+ "order": null,
+ "overflow": null,
+ "overflow_x": null,
+ "overflow_y": null,
+ "padding": null,
+ "right": null,
+ "top": null,
+ "visibility": null,
+ "width": null
+ }
+ },
+ "abba39fb52344edd86567aa053860b3a": {
+ "model_module": "@jupyter-widgets/controls",
+ "model_name": "DescriptionStyleModel",
+ "model_module_version": "1.5.0",
+ "state": {
+ "_model_module": "@jupyter-widgets/controls",
+ "_model_module_version": "1.5.0",
+ "_model_name": "DescriptionStyleModel",
+ "_view_count": null,
+ "_view_module": "@jupyter-widgets/base",
+ "_view_module_version": "1.2.0",
+ "_view_name": "StyleView",
+ "description_width": ""
+ }
+ }
+ }
+ },
+ "accelerator": "GPU"
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "view-in-github",
+ "colab_type": "text"
+ },
+ "source": [
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# MHub Universal Notebook\n",
+ "\n",
+ "This notebook demonstrates how to run models from [MHub.ai](https://mhub.ai) using [Imaging Data Commons (IDC)](https://portal.imaging.datacommons.cancer.gov/) data.\n",
+ "\n",
+ "MHub is a novel platform, providing standardized medical imaging models with a harmonized I/O interface. MHub models are originally containerized to provide platform agnostic models that can be run locally or in the cloud without additional environmental setup. However, as it is not possible to run Docker images from within a Colab notebook, we instead setup the environment in the notebook based on the instructions outlined in the Dockerfile.\n"
+ ],
+ "metadata": {
+ "id": "fZ6lYPDutv-t"
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Disclaimer\n",
+ "\n",
+ "The code and data of this repository are provided to promote reproducible research. They are not intended for clinical care or commercial use.\n",
+ "\n",
+ "The software is provided \"as is\", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the software."
+ ],
+ "metadata": {
+ "id": "zxxshCxFvwdi"
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Global Variables\n"
+ ],
+ "metadata": {
+ "id": "yJLRHiDh-7J_"
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "Together with the project id, we also set the default MHub model the notebook will be running if the user doesn't want to interact with the model selection dropdown."
+ ],
+ "metadata": {
+ "id": "amuU0WeHCwLC"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "\n",
+ "MHUB_MODEL_NAME = \"lungmask\" # @param {type:\"string\"}"
+ ],
+ "metadata": {
+ "id": "4hyGYUXR--1B"
+ },
+ "execution_count": 18,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "## Notebook Setup\n",
+ "\n",
+ "Let's start by installing all the dependencies needed for this project.\n",
+ "\n",
+ "We install `ipywidgets` and `itkwidgets` to display interactive controls and visualize medical images in the notebook.\n",
+ "\n",
+ "Then we install [`idc-index`](https://github.com/ImagingDataCommons/idc-index), a package for simplified access to IDC data.\n",
+ "\n",
+ "As mentioned earlier, all MHub models are usually run in a Docker container, and following convention, the `/app` directory is used as the working directory. We'll clean up the `/content` folder (we don't need any of the files created with each new Colab instance) and set a symlink to the `/app` folder for your convenience. We recommend you open the *file browser* on the left to see what files are created during the course of this notebook.\n",
+ "\n",
+ "*If you want to open the `/content` folder, click the following link: /content/../content*"
+ ],
+ "metadata": {
+ "id": "OJoBa-Vhw08P"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "%%capture\n",
+ "\n",
+ "# install ipywidgets\n",
+ "!pip install --upgrade google-colab\n",
+ "!pip install ipywidgets\n",
+ "!pip install itkwidgets[all]==1.0a32\n",
+ "\n",
+ "# install idc-index\n",
+ "!pip install 'idc-index>=0.2.10'\n",
+ "\n",
+ "# delete content folder, create app folder and symlink /content -> /app\n",
+ "!rm -r /content/*\n",
+ "!ln -s /app /content"
+ ],
+ "metadata": {
+ "id": "99cSW_p0hWUT"
+ },
+ "execution_count": 19,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "Import all Python libraries used throughout this notebook."
+ ],
+ "metadata": {
+ "id": "7NEzkB7gwqwO"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import subprocess\n",
+ "import os\n",
+ "import time\n",
+ "import json\n",
+ "\n",
+ "import ipywidgets as widgets\n",
+ "\n",
+ "from idc_index import index\n",
+ "idc_client = index.IDCClient()\n",
+ "\n",
+ "from urllib.request import urlopen"
+ ],
+ "metadata": {
+ "id": "Qy5yc4ExrPRI"
+ },
+ "execution_count": 20,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Helper Functions\n",
+ "\n",
+ "The following two cells contain helper functions we will use throughout the notebook. For instance, the functions we use to convert the MHub base and model specific Dockerfiles into a `setup.sh` script to setup the environment, and utility functions to download sample patients from the Imaging Data Commons platform."
+ ],
+ "metadata": {
+ "id": "xshLGkbfBcgi"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "def docker2bash(dockerfile_path, bashscript_path):\n",
+ " \"\"\"\n",
+ " Extract commands from a Dockerfile and convert them into a bash script.\n",
+ "\n",
+ " Arguments:\n",
+ " dockerfile_path : required - path to the Dockerfile to be converted.\n",
+ " bashscript_path : required - path to the bash script were the extracted\n",
+ " commands will be appended to.\n",
+ " \"\"\"\n",
+ "\n",
+ " # read Dockerfile into array\n",
+ " with open(dockerfile_path, 'r') as f:\n",
+ " dockerfile = f.read().split('\\n')\n",
+ "\n",
+ " # iterate dockerfiles line by line and generate export commands\n",
+ " run = []\n",
+ " inrun = False\n",
+ " for line in dockerfile:\n",
+ " if line.startswith('WORKDIR'):\n",
+ " run.append(\"cd \" + line.lstrip(\"WORKDIR\"))\n",
+ " elif line.startswith('ENV'):\n",
+ " run.append(\"export \" + line.lstrip(\"ENV\"))\n",
+ " elif line.startswith('RUN'):\n",
+ " run.append(line.strip().lstrip('RUN').rstrip('\\\\').strip())\n",
+ " inrun = line.strip().endswith('\\\\')\n",
+ " elif inrun:\n",
+ " run[len(run)-1] += \" \" + line.strip().rstrip('\\\\').strip()\n",
+ " inrun = line.strip().endswith('\\\\')\n",
+ "\n",
+ " # write extracted commands to bash script\n",
+ " with open(bashscript_path, 'a') as fp:\n",
+ " fp.write('\\n'.join(run) + '\\n')\n"
+ ],
+ "metadata": {
+ "id": "D5PZELW1GEVq"
+ },
+ "execution_count": 21,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "def patch_setup_bash(bashscript_path = '/content/setup.sh'):\n",
+ " new_lines = []\n",
+ "\n",
+ " # patch bash script (#plastimatch ubuntu22 issue)\n",
+ " with open(bashscript_path, 'r') as fp:\n",
+ " lines = fp.readlines()\n",
+ "\n",
+ " for line in lines:\n",
+ " #print(line.strip())\n",
+ " if line.strip() == 'apt update && apt install -y --no-install-recommends libopenslide-dev libvips-dev plastimatch dcm2niix ffmpeg libsm6 libxext6 && rm -rf /var/lib/apt/lists/*':\n",
+ " new_lines.append('apt update && apt install -y --no-install-recommends libopenslide-dev libvips-dev dcm2niix ffmpeg libsm6 libxext6 && rm -rf /var/lib/apt/lists/*')\n",
+ " new_lines.append(\"pip3 install pyplastimatch && python3 -c 'from pyplastimatch.utils.install import install_precompiled_binaries; install_precompiled_binaries()'\")\n",
+ " elif len(line.strip()):\n",
+ " new_lines.append(line.strip())\n",
+ "\n",
+ " with open(bashscript_path, 'w') as fp:\n",
+ " fp.write('\\n'.join(new_lines) + '\\n')"
+ ],
+ "metadata": {
+ "id": "NYfZQ6UYFPOe"
+ },
+ "execution_count": 22,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "def setup_environment(\n",
+ " dockerfiles_paths,\n",
+ " bashscript_path = '/content/setup.sh',\n",
+ " env_path = '/content/env_vars.txt'\n",
+ " ):\n",
+ "\n",
+ " # make sure we start with an empty setup.sh script\n",
+ " if os.path.isfile(bashscript_path):\n",
+ " os.remove(bashscript_path)\n",
+ "\n",
+ " # generate bash script from dockerfiles\n",
+ " for dockerfile_path in dockerfiles_paths:\n",
+ " docker2bash(dockerfile_path, bashscript_path)\n",
+ "\n",
+ " # patch setup bash script\n",
+ " patch_setup_bash(bashscript_path)\n",
+ "\n",
+ " # append environment export\n",
+ " with open(bashscript_path, 'a') as fp:\n",
+ " fp.write('\\n' + 'env > ' + env_path + '\\n')\n",
+ "\n",
+ " # run setup script\n",
+ " !chmod +x $bashscript_path\n",
+ " !$bashscript_path\n",
+ "\n",
+ " # load environment variables from the file\n",
+ " with open(env_path, 'r') as f:\n",
+ " for line in f:\n",
+ " key, value = line.strip().split('=', 1)\n",
+ " os.environ[key] = value"
+ ],
+ "metadata": {
+ "id": "fWBU4Lc2KIJb"
+ },
+ "execution_count": 23,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "def get_idc_viewer_url(studyUID, seriesUID=None):\n",
+ " url = \"https://viewer.imaging.datacommons.cancer.gov/viewer/\"+studyUID\n",
+ " if seriesUID is not None:\n",
+ " url = url+\"?seriesInstanceUID=\"+seriesUID\n",
+ " return url"
+ ],
+ "metadata": {
+ "id": "VH0B0vnjJlU8"
+ },
+ "execution_count": 24,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Select the MHub Model\n",
+ "\n",
+ "MHub hosts several pre-trained models for the analysis of CT scans, all of which are harmonized and share a common interface - so you can swap models by simply swapping model names in the run command!\n",
+ "\n",
+ "You can learn more about all the models (including the data they have been trained and evaluated on) by visiting the https://mhub.ai/models page."
+ ],
+ "metadata": {
+ "id": "Y5bwi4_PU73u"
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ ""
+ ],
+ "metadata": {
+ "id": "g3lMtU_1NB8o"
+ }
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "---\n",
+ "\n",
+ "
\n",
+ "\n",
+ "We can fetch a list of all available MHub models through the MHub.ai API.\n",
+ "\n",
+ "Running the following two cells will spawn a dropdown box where you can select the model you would like to run in the notebook."
+ ],
+ "metadata": {
+ "id": "D598_0yCLPDe"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# fetch the mhub.ai api\n",
+ "MHUBAI_MODELS_ENDPOINT = \"https://mhub.ai/api/v2/models\"\n",
+ "\n",
+ "# fetch information on the models on the platform\n",
+ "models = json.loads(urlopen(MHUBAI_MODELS_ENDPOINT).read())['data']['models']\n",
+ "\n",
+ "# generate model picker\n",
+ "model_picker = widgets.Dropdown(options=models, value=MHUB_MODEL_NAME)"
+ ],
+ "metadata": {
+ "id": "vCX6A8DfVT4Y"
+ },
+ "execution_count": 25,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# display model picker\n",
+ "display(model_picker)"
+ ],
+ "metadata": {
+ "id": "kt11JzYwVZx2",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 49,
+ "referenced_widgets": [
+ "717d4dacb81a4529b7e475d1b217568b",
+ "815a58f1a77740759d70aafe8c929d38",
+ "abba39fb52344edd86567aa053860b3a"
+ ]
+ },
+ "outputId": "bb6ffd25-a68b-4336-e78e-25a5f0428a88"
+ },
+ "execution_count": 26,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/plain": [
+ "Dropdown(index=1, options=('gc_lunglobes', 'lungmask', 'nnunet_pancreas', 'totalsegmentator', 'platipy', 'casu…"
+ ],
+ "application/vnd.jupyter.widget-view+json": {
+ "version_major": 2,
+ "version_minor": 0,
+ "model_id": "717d4dacb81a4529b7e475d1b217568b"
+ }
+ },
+ "metadata": {}
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# print choice\n",
+ "print(\"Selected Model: \", model_picker.value)"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "oK5NfDEragwO",
+ "outputId": "07e32975-fd13-4f9c-d340-a321f8e5d842"
+ },
+ "execution_count": 27,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Selected Model: lungmask\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Model Environment Setup\n",
+ "\n",
+ "The next series of cell will take care of the model environment set-up. This process is essentially automated, and closely mimicks what happens inside an MHub container. We start by cloning the model folder from the MHub [Models Repository](https://github.com/MHubAI/models), based on the model selection made earlier.\n",
+ "\n",
+ "We then extract the base Dockerfile and the Dockerfile of the model and pass both to our helper function `setup_environment`, which reads the Dockerfiles and sets up the environment accordingly.\n",
+ "\n",
+ "**NOTE**: This step can take up to several minutes since setting up the environment involves downloading model weights with large file sizes."
+ ],
+ "metadata": {
+ "id": "SY-KhiXn860d"
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 28,
+ "metadata": {
+ "id": "sOJsHBglq9CH"
+ },
+ "outputs": [],
+ "source": [
+ "%%capture\n",
+ "\n",
+ "# clone the model repository\n",
+ "!git init && git sparse-checkout set \"base\" \"models/{model_picker.value}\" \\\n",
+ " && git fetch https://github.com/MHubAI/models.git main \\\n",
+ " && git merge FETCH_HEAD \\\n",
+ " && rm -rf .git"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# setup the environment from Dockerfiles\n",
+ "setup_environment([\n",
+ " f'/content/base/dockerfiles/Dockerfile',\n",
+ " f'/content/models/{model_picker.value}/dockerfiles/Dockerfile'\n",
+ "])"
+ ],
+ "metadata": {
+ "id": "VOyEtayDwyPZ",
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "outputId": "219d4ddb-aa99-4a5c-ea13-55d0a357317b"
+ },
+ "execution_count": 29,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "mkdir: cannot create directory ‘/app’: File exists\n",
+ "mkdir: cannot create directory ‘/app/data’: File exists\n",
+ "mkdir: cannot create directory ‘/app/data/input_data’: File exists\n",
+ "mkdir: cannot create directory ‘/app/data/output_data’: File exists\n",
+ "\u001b[33m\r0% [Working]\u001b[0m\r \rHit:1 http://archive.ubuntu.com/ubuntu jammy InRelease\n",
+ "\u001b[33m\r0% [Connecting to security.ubuntu.com (91.189.91.82)]\u001b[0m\r \rHit:2 http://archive.ubuntu.com/ubuntu jammy-updates InRelease\n",
+ "\u001b[33m\r \r0% [Waiting for headers] [Waiting for headers]\u001b[0m\r \rHit:3 http://security.ubuntu.com/ubuntu jammy-security InRelease\n",
+ "Hit:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease\n",
+ "Reading package lists... Done\n",
+ "Building dependency tree... Done\n",
+ "Reading state information... Done\n",
+ "23 packages can be upgraded. Run 'apt list --upgradable' to see them.\n",
+ "Reading package lists... Done\n",
+ "Building dependency tree... Done\n",
+ "Reading state information... Done\n",
+ "gcc is already the newest version (4:11.2.0-1ubuntu1).\n",
+ "jq is already the newest version (1.6-2.1ubuntu3).\n",
+ "wget is already the newest version (1.21.2-2ubuntu1).\n",
+ "curl is already the newest version (7.81.0-1ubuntu1.15).\n",
+ "git is already the newest version (1:2.34.1-1ubuntu1.10).\n",
+ "python3 is already the newest version (3.10.6-1~22.04).\n",
+ "sudo is already the newest version (1.9.9-1ubuntu2.4).\n",
+ "unzip is already the newest version (6.0-26ubuntu3.1).\n",
+ "python3-pip is already the newest version (22.0.2+dfsg-1ubuntu0.4).\n",
+ "0 upgraded, 0 newly installed, 0 to remove and 23 not upgraded.\n",
+ "Hit:1 http://security.ubuntu.com/ubuntu jammy-security InRelease\n",
+ "Hit:2 http://archive.ubuntu.com/ubuntu jammy InRelease\n",
+ "Hit:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease\n",
+ "Hit:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease\n",
+ "Reading package lists... Done\n",
+ "Building dependency tree... Done\n",
+ "Reading state information... Done\n",
+ "23 packages can be upgraded. Run 'apt list --upgradable' to see them.\n",
+ "Reading package lists... Done\n",
+ "Building dependency tree... Done\n",
+ "Reading state information... Done\n",
+ "libsm6 is already the newest version (2:1.2.3-1build2).\n",
+ "libxext6 is already the newest version (2:1.3.4-1build1).\n",
+ "dcm2niix is already the newest version (1.0.20211006-1build1).\n",
+ "libopenslide-dev is already the newest version (3.4.1+dfsg-5build1).\n",
+ "libvips-dev is already the newest version (8.12.1-1build1).\n",
+ "ffmpeg is already the newest version (7:4.4.2-0ubuntu0.22.04.1).\n",
+ "0 upgraded, 0 newly installed, 0 to remove and 23 not upgraded.\n",
+ "Requirement already satisfied: pyplastimatch in /usr/local/lib/python3.10/dist-packages (0.4.3)\n",
+ "Requirement already satisfied: itk in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: matplotlib in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (3.7.1)\n",
+ "Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (1.26.3)\n",
+ "Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (2.2.0)\n",
+ "Requirement already satisfied: pydicom in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (2.4.4)\n",
+ "Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (2.31.0)\n",
+ "Requirement already satisfied: scikit-image in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (0.19.3)\n",
+ "Requirement already satisfied: SimpleITK in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (2.2.1)\n",
+ "Requirement already satisfied: itk-core==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-numerics==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-io==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-filtering==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-registration==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-segmentation==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (1.2.0)\n",
+ "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (0.12.1)\n",
+ "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (4.47.2)\n",
+ "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (1.4.5)\n",
+ "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (23.2)\n",
+ "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (9.5.0)\n",
+ "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (3.1.1)\n",
+ "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (2.8.2)\n",
+ "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas->pyplastimatch) (2023.3.post1)\n",
+ "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.10/dist-packages (from pandas->pyplastimatch) (2023.4)\n",
+ "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (3.3.2)\n",
+ "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (3.6)\n",
+ "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (2.0.7)\n",
+ "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (2023.11.17)\n",
+ "Requirement already satisfied: scipy>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (1.11.4)\n",
+ "Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (3.2.1)\n",
+ "Requirement already satisfied: imageio>=2.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (2.31.6)\n",
+ "Requirement already satisfied: tifffile>=2019.7.26 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (2023.12.9)\n",
+ "Requirement already satisfied: PyWavelets>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (1.5.0)\n",
+ "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.7->matplotlib->pyplastimatch) (1.16.0)\n",
+ "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
+ "\u001b[0mPyPlastimatch Plastimatch installation utility.\n",
+ "NOTE: this utility is not meant to be replace the normal install of Plastimatch via apt.\n",
+ "Rather, it is meant to be used in case a Plastimatch binary is not available for a specific distribution.\n",
+ "\n",
+ "System distribution: Ubuntu 22.04\n",
+ "\n",
+ "Downloading meta JSON in the temp directory /tmp/tmp5_ofolrf/release_meta.json... Done.\n",
+ "Matching distribution found in the latest PyPlastimatch release.\n",
+ "\n",
+ "Downloading binary in the temp directory /tmp/tmp5_ofolrf/plastimatch-ubuntu_22_04... Done.\n",
+ "\n",
+ "Installing binaries... Done.\n",
+ "Installing dependencies... Done.\n",
+ "Requirement already satisfied: pip in /usr/local/lib/python3.10/dist-packages (23.3.2)\n",
+ "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
+ "\u001b[0mRequirement already satisfied: typing-extensions in /usr/local/lib/python3.10/dist-packages (4.9.0)\n",
+ "Requirement already satisfied: Pillow==9.5.0 in /usr/local/lib/python3.10/dist-packages (9.5.0)\n",
+ "Requirement already satisfied: h5py in /usr/local/lib/python3.10/dist-packages (3.9.0)\n",
+ "Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (1.26.3)\n",
+ "Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (2.2.0)\n",
+ "Requirement already satisfied: panimg in /usr/local/lib/python3.10/dist-packages (0.13.2)\n",
+ "Requirement already satisfied: pydicom in /usr/local/lib/python3.10/dist-packages (2.4.4)\n",
+ "Requirement already satisfied: pydicom-seg in /usr/local/lib/python3.10/dist-packages (0.4.1)\n",
+ "Requirement already satisfied: rt_utils in /usr/local/lib/python3.10/dist-packages (1.2.7)\n",
+ "Requirement already satisfied: PyYAML in /usr/local/lib/python3.10/dist-packages (6.0.1)\n",
+ "Requirement already satisfied: pyplastimatch in /usr/local/lib/python3.10/dist-packages (0.4.3)\n",
+ "Requirement already satisfied: SimpleITK==2.2.1 in /usr/local/lib/python3.10/dist-packages (2.2.1)\n",
+ "Requirement already satisfied: thedicomsort in /usr/local/lib/python3.10/dist-packages (1.0.1)\n",
+ "Requirement already satisfied: colorspacious in /usr/local/lib/python3.10/dist-packages (1.1.2)\n",
+ "Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.10/dist-packages (from pandas) (2.8.2)\n",
+ "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas) (2023.3.post1)\n",
+ "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.10/dist-packages (from pandas) (2023.4)\n",
+ "Requirement already satisfied: click in /usr/local/lib/python3.10/dist-packages (from panimg) (8.1.7)\n",
+ "Requirement already satisfied: construct in /usr/local/lib/python3.10/dist-packages (from panimg) (2.10.70)\n",
+ "Requirement already satisfied: imagecodecs>=2023.3.16 in /usr/local/lib/python3.10/dist-packages (from panimg) (2024.1.1)\n",
+ "Requirement already satisfied: openslide-python in /usr/local/lib/python3.10/dist-packages (from panimg) (1.3.1)\n",
+ "Requirement already satisfied: pydantic>=2 in /usr/local/lib/python3.10/dist-packages (from panimg) (2.5.3)\n",
+ "Requirement already satisfied: pylibjpeg in /usr/local/lib/python3.10/dist-packages (from panimg) (2.0.0)\n",
+ "Requirement already satisfied: pylibjpeg-libjpeg in /usr/local/lib/python3.10/dist-packages (from panimg) (2.0.2)\n",
+ "Requirement already satisfied: pylibjpeg-openjpeg in /usr/local/lib/python3.10/dist-packages (from panimg) (2.1.1)\n",
+ "Requirement already satisfied: pyvips in /usr/local/lib/python3.10/dist-packages (from panimg) (2.2.2)\n",
+ "Requirement already satisfied: tifffile in /usr/local/lib/python3.10/dist-packages (from panimg) (2023.12.9)\n",
+ "Requirement already satisfied: wsidicom>=0.10.0 in /usr/local/lib/python3.10/dist-packages (from panimg) (0.18.3)\n",
+ "Collecting jsonschema<4.0.0,>=3.2.0 (from pydicom-seg)\n",
+ " Downloading jsonschema-3.2.0-py2.py3-none-any.whl (56 kB)\n",
+ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m56.3/56.3 kB\u001b[0m \u001b[31m1.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+ "\u001b[?25hRequirement already satisfied: opencv-python in /usr/local/lib/python3.10/dist-packages (from rt_utils) (4.8.0.76)\n",
+ "Requirement already satisfied: dataclasses in /usr/local/lib/python3.10/dist-packages (from rt_utils) (0.6)\n",
+ "Requirement already satisfied: itk in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: matplotlib in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (3.7.1)\n",
+ "Requirement already satisfied: requests in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (2.31.0)\n",
+ "Requirement already satisfied: scikit-image in /usr/local/lib/python3.10/dist-packages (from pyplastimatch) (0.19.3)\n",
+ "Requirement already satisfied: tqdm<5.0.0,>=4.64.1 in /usr/local/lib/python3.10/dist-packages (from thedicomsort) (4.66.1)\n",
+ "Requirement already satisfied: attrs>=17.4.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema<4.0.0,>=3.2.0->pydicom-seg) (23.2.0)\n",
+ "Requirement already satisfied: pyrsistent>=0.14.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema<4.0.0,>=3.2.0->pydicom-seg) (0.20.0)\n",
+ "Requirement already satisfied: setuptools in /usr/local/lib/python3.10/dist-packages (from jsonschema<4.0.0,>=3.2.0->pydicom-seg) (67.7.2)\n",
+ "Requirement already satisfied: six>=1.11.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema<4.0.0,>=3.2.0->pydicom-seg) (1.16.0)\n",
+ "Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->panimg) (0.6.0)\n",
+ "Requirement already satisfied: pydantic-core==2.14.6 in /usr/local/lib/python3.10/dist-packages (from pydantic>=2->panimg) (2.14.6)\n",
+ "Requirement already satisfied: dicomweb-client<0.60.0,>=0.59.1 in /usr/local/lib/python3.10/dist-packages (from wsidicom>=0.10.0->panimg) (0.59.1)\n",
+ "Requirement already satisfied: marshmallow<4.0.0,>=3.20.1 in /usr/local/lib/python3.10/dist-packages (from wsidicom>=0.10.0->panimg) (3.20.2)\n",
+ "Requirement already satisfied: itk-core==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-numerics==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-io==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-filtering==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-registration==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: itk-segmentation==5.3.0 in /usr/local/lib/python3.10/dist-packages (from itk->pyplastimatch) (5.3.0)\n",
+ "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (1.2.0)\n",
+ "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (0.12.1)\n",
+ "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (4.47.2)\n",
+ "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (1.4.5)\n",
+ "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (23.2)\n",
+ "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib->pyplastimatch) (3.1.1)\n",
+ "Requirement already satisfied: cffi>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from pyvips->panimg) (1.16.0)\n",
+ "Requirement already satisfied: pkgconfig in /usr/local/lib/python3.10/dist-packages (from pyvips->panimg) (1.5.5)\n",
+ "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (3.3.2)\n",
+ "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (3.6)\n",
+ "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (2.0.7)\n",
+ "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests->pyplastimatch) (2023.11.17)\n",
+ "Requirement already satisfied: scipy>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (1.11.4)\n",
+ "Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (3.2.1)\n",
+ "Requirement already satisfied: imageio>=2.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (2.31.6)\n",
+ "Requirement already satisfied: PyWavelets>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->pyplastimatch) (1.5.0)\n",
+ "Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.0.0->pyvips->panimg) (2.21)\n",
+ "Requirement already satisfied: retrying>=1.3.3 in /usr/local/lib/python3.10/dist-packages (from dicomweb-client<0.60.0,>=0.59.1->wsidicom>=0.10.0->panimg) (1.3.4)\n",
+ "Installing collected packages: jsonschema\n",
+ " Attempting uninstall: jsonschema\n",
+ " Found existing installation: jsonschema 4.21.1\n",
+ " Uninstalling jsonschema-4.21.1:\n",
+ " Successfully uninstalled jsonschema-4.21.1\n",
+ "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n",
+ "lida 0.0.10 requires kaleido, which is not installed.\n",
+ "jupyter-events 0.9.0 requires jsonschema[format-nongpl]>=4.18.0, but you have jsonschema 3.2.0 which is incompatible.\n",
+ "jupyterlab-server 2.25.2 requires jsonschema>=4.18.0, but you have jsonschema 3.2.0 which is incompatible.\u001b[0m\u001b[31m\n",
+ "\u001b[0mSuccessfully installed jsonschema-3.2.0\n",
+ "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
+ "\u001b[0mCollecting git+https://github.com/MHubAI/mhubio.git\n",
+ " Cloning https://github.com/MHubAI/mhubio.git to /tmp/pip-req-build-w31judqm\n",
+ " Running command git clone --filter=blob:none --quiet https://github.com/MHubAI/mhubio.git /tmp/pip-req-build-w31judqm\n",
+ " Resolved https://github.com/MHubAI/mhubio.git to commit e7fa6603a62b640b2cf14b5bd98bebe894fc0374\n",
+ " Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+ "Requirement already satisfied: pyyaml in /usr/local/lib/python3.10/dist-packages (from mhubio==0.0.2) (6.0.1)\n",
+ "Requirement already satisfied: typing_extensions<5.0.0,>=4.5.0 in /usr/local/lib/python3.10/dist-packages (from mhubio==0.0.2) (4.9.0)\n",
+ "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
+ "\u001b[0mCollecting git+https://github.com/MHubAI/segdb.git\n",
+ " Cloning https://github.com/MHubAI/segdb.git to /tmp/pip-req-build-vkjhv5pt\n",
+ " Running command git clone --filter=blob:none --quiet https://github.com/MHubAI/segdb.git /tmp/pip-req-build-vkjhv5pt\n",
+ " Resolved https://github.com/MHubAI/segdb.git to commit 79add4b3176b3676673edef4fad32a18e9770d39\n",
+ " Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+ "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
+ "\u001b[0m\u001b[33mhint: Using 'master' as the name for the initial branch. This default branch name\u001b[m\n",
+ "\u001b[33mhint: is subject to change. To configure the initial branch name to use in all\u001b[m\n",
+ "\u001b[33mhint: of your new repositories, which will suppress this warning, call:\u001b[m\n",
+ "\u001b[33mhint: \u001b[m\n",
+ "\u001b[33mhint: \tgit config --global init.defaultBranch \u001b[m\n",
+ "\u001b[33mhint: \u001b[m\n",
+ "\u001b[33mhint: Names commonly chosen instead of 'master' are 'main', 'trunk' and\u001b[m\n",
+ "\u001b[33mhint: 'development'. The just-created branch can be renamed via this command:\u001b[m\n",
+ "\u001b[33mhint: \u001b[m\n",
+ "\u001b[33mhint: \tgit branch -m \u001b[m\n",
+ "Initialized empty Git repository in /app/.git/\n",
+ "remote: Enumerating objects: 1511, done.\u001b[K\n",
+ "remote: Counting objects: 100% (255/255), done.\u001b[K\n",
+ "remote: Compressing objects: 100% (166/166), done.\u001b[K\n",
+ "remote: Total 1511 (delta 138), reused 128 (delta 86), pack-reused 1256\u001b[K\n",
+ "Receiving objects: 100% (1511/1511), 233.39 KiB | 3.07 MiB/s, done.\n",
+ "Resolving deltas: 100% (711/711), done.\n",
+ "From https://github.com/MHubAI/models\n",
+ " * branch main -> FETCH_HEAD\n",
+ "mv: cannot move 'base/buildutils' to './buildutils': Directory not empty\n",
+ "--2024-01-26 19:59:26-- https://github.com/QIICR/dcmqi/releases/download/v1.3.1/dcmqi-1.3.1-linux.tar.gz\n",
+ "Resolving github.com (github.com)... 140.82.112.4\n",
+ "Connecting to github.com (github.com)|140.82.112.4|:443... connected.\n",
+ "HTTP request sent, awaiting response... 302 Found\n",
+ "Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/50675718/2d2a3113-dfd9-433d-8f32-1dbe5684d6c1?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240126T185927Z&X-Amz-Expires=300&X-Amz-Signature=1b41abb5a27d5574a4b4dcc78cbba8940df2bafbd637958ac9ad2157e9d540e0&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=50675718&response-content-disposition=attachment%3B%20filename%3Ddcmqi-1.3.1-linux.tar.gz&response-content-type=application%2Foctet-stream [following]\n",
+ "--2024-01-26 19:59:27-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/50675718/2d2a3113-dfd9-433d-8f32-1dbe5684d6c1?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240126T185927Z&X-Amz-Expires=300&X-Amz-Signature=1b41abb5a27d5574a4b4dcc78cbba8940df2bafbd637958ac9ad2157e9d540e0&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=50675718&response-content-disposition=attachment%3B%20filename%3Ddcmqi-1.3.1-linux.tar.gz&response-content-type=application%2Foctet-stream\n",
+ "Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
+ "Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.108.133|:443... connected.\n",
+ "HTTP request sent, awaiting response... 200 OK\n",
+ "Length: 40452257 (39M) [application/octet-stream]\n",
+ "Saving to: ‘/app/dcmqi-1.3.1-linux.tar.gz’\n",
+ "\n",
+ "/app/dcmqi-1.3.1-li 100%[===================>] 38.58M 185MB/s in 0.2s \n",
+ "\n",
+ "2024-01-26 19:59:27 (185 MB/s) - ‘/app/dcmqi-1.3.1-linux.tar.gz’ saved [40452257/40452257]\n",
+ "\n",
+ "dcmqi-1.3.1-linux/share/\n",
+ "dcmqi-1.3.1-linux/share/doc/\n",
+ "dcmqi-1.3.1-linux/share/doc/ITK-5.3/\n",
+ "dcmqi-1.3.1-linux/share/doc/ITK-5.3/itksys/\n",
+ "dcmqi-1.3.1-linux/share/doc/ITK-5.3/itksys/Copyright.txt\n",
+ "dcmqi-1.3.1-linux/bin/\n",
+ "dcmqi-1.3.1-linux/bin/itkimage2segimage.xml\n",
+ "dcmqi-1.3.1-linux/bin/itkimage2paramap\n",
+ "dcmqi-1.3.1-linux/bin/paramap2itkimage.xml\n",
+ "dcmqi-1.3.1-linux/bin/tid1500reader.xml\n",
+ "dcmqi-1.3.1-linux/bin/tid1500reader\n",
+ "dcmqi-1.3.1-linux/bin/itkimage2paramap.xml\n",
+ "dcmqi-1.3.1-linux/bin/itkimage2segimage\n",
+ "dcmqi-1.3.1-linux/bin/tid1500writer.xml\n",
+ "dcmqi-1.3.1-linux/bin/tid1500writer\n",
+ "dcmqi-1.3.1-linux/bin/paramap2itkimage\n",
+ "dcmqi-1.3.1-linux/bin/segimage2itkimage.xml\n",
+ "dcmqi-1.3.1-linux/bin/segimage2itkimage\n",
+ "dcmqi-1.3.1-linux/lib/\n",
+ "dcmqi-1.3.1-linux/lib/dcmqi-1.3/\n",
+ "dcmqi-1.3.1-linux/lib/dcmqi-1.3/libITKznz-5.3.a\n",
+ "dcmqi-1.3.1-linux/lib/dcmqi-1.3/libITKniftiio-5.3.a\n",
+ "Requirement already satisfied: lungmask==0.2.16 in /usr/local/lib/python3.10/dist-packages (0.2.16)\n",
+ "Requirement already satisfied: pydicom in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (2.4.4)\n",
+ "Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (1.26.3)\n",
+ "Requirement already satisfied: torch in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (2.1.0+cu121)\n",
+ "Requirement already satisfied: scipy in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (1.11.4)\n",
+ "Requirement already satisfied: SimpleITK in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (2.2.1)\n",
+ "Requirement already satisfied: tqdm in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (4.66.1)\n",
+ "Requirement already satisfied: scikit-image in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (0.19.3)\n",
+ "Requirement already satisfied: fill-voids in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (2.0.6)\n",
+ "Requirement already satisfied: more-itertools in /usr/local/lib/python3.10/dist-packages (from lungmask==0.2.16) (10.1.0)\n",
+ "Requirement already satisfied: fastremap in /usr/local/lib/python3.10/dist-packages (from fill-voids->lungmask==0.2.16) (1.14.1)\n",
+ "Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.10/dist-packages (from scikit-image->lungmask==0.2.16) (3.2.1)\n",
+ "Requirement already satisfied: pillow!=7.1.0,!=7.1.1,!=8.3.0,>=6.1.0 in /usr/local/lib/python3.10/dist-packages (from scikit-image->lungmask==0.2.16) (9.5.0)\n",
+ "Requirement already satisfied: imageio>=2.4.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->lungmask==0.2.16) (2.31.6)\n",
+ "Requirement already satisfied: tifffile>=2019.7.26 in /usr/local/lib/python3.10/dist-packages (from scikit-image->lungmask==0.2.16) (2023.12.9)\n",
+ "Requirement already satisfied: PyWavelets>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-image->lungmask==0.2.16) (1.5.0)\n",
+ "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from scikit-image->lungmask==0.2.16) (23.2)\n",
+ "Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from torch->lungmask==0.2.16) (3.13.1)\n",
+ "Requirement already satisfied: typing-extensions in /usr/local/lib/python3.10/dist-packages (from torch->lungmask==0.2.16) (4.9.0)\n",
+ "Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch->lungmask==0.2.16) (1.12)\n",
+ "Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from torch->lungmask==0.2.16) (3.1.3)\n",
+ "Requirement already satisfied: fsspec in /usr/local/lib/python3.10/dist-packages (from torch->lungmask==0.2.16) (2023.6.0)\n",
+ "Requirement already satisfied: triton==2.1.0 in /usr/local/lib/python3.10/dist-packages (from torch->lungmask==0.2.16) (2.1.0)\n",
+ "Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2->torch->lungmask==0.2.16) (2.1.4)\n",
+ "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->torch->lungmask==0.2.16) (1.3.0)\n",
+ "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv\u001b[0m\u001b[33m\n",
+ "\u001b[0mImporting model definition from MHub models repository.\n",
+ "├── MODEL NAME ..... lungmask\n",
+ "├── REPOSITORY ..... https://github.com/MHubAI/models.git\n",
+ "└── BRANCH ......... main\n",
+ "\n",
+ "Reinitialized existing Git repository in /app/.git/\n",
+ "From https://github.com/MHubAI/models\n",
+ " * branch main -> FETCH_HEAD\n",
+ "Already up to date.\n",
+ "warning: The following paths were already present and thus not updated despite sparse patterns:\n",
+ "\tmodels/lungmask/README.md\n",
+ "\tmodels/lungmask/__init__.py\n",
+ "\tmodels/lungmask/config/default.yml\n",
+ "\tmodels/lungmask/config/slicer.yml\n",
+ "\tmodels/lungmask/dockerfiles/Dockerfile\n",
+ "\tmodels/lungmask/meta.json\n",
+ "\tmodels/lungmask/utils/LungMaskRunner.py\n",
+ "\n",
+ "After fixing the above paths, you may want to run `git sparse-checkout reapply`.\n",
+ "\n",
+ "Imported model definition from MHub models repository.\n",
+ "└── COMMIT HASH .... 6a9c22c23a45874c794522112d6975e0b3af216f\n",
+ "\n",
+ "--2024-01-26 19:59:35-- https://github.com/JoHof/lungmask/releases/download/v0.0/unet_r231-d5d2fc3d.pth\n",
+ "Resolving github.com (github.com)... 140.82.112.4\n",
+ "Connecting to github.com (github.com)|140.82.112.4|:443... connected.\n",
+ "HTTP request sent, awaiting response... 302 Found\n",
+ "Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/224678136/40e91380-517d-11ea-91d3-50021647603c?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240126T185935Z&X-Amz-Expires=300&X-Amz-Signature=691c7d3f98f89f824bd68d088644cefc765bd74c7da428621c3b81110ac4913b&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=224678136&response-content-disposition=attachment%3B%20filename%3Dunet_r231-d5d2fc3d.pth&response-content-type=application%2Foctet-stream [following]\n",
+ "--2024-01-26 19:59:35-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/224678136/40e91380-517d-11ea-91d3-50021647603c?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240126T185935Z&X-Amz-Expires=300&X-Amz-Signature=691c7d3f98f89f824bd68d088644cefc765bd74c7da428621c3b81110ac4913b&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=224678136&response-content-disposition=attachment%3B%20filename%3Dunet_r231-d5d2fc3d.pth&response-content-type=application%2Foctet-stream\n",
+ "Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.108.133, 185.199.109.133, 185.199.110.133, ...\n",
+ "Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.108.133|:443... connected.\n",
+ "HTTP request sent, awaiting response... 200 OK\n",
+ "Length: 124340403 (119M) [application/octet-stream]\n",
+ "Saving to: ‘/root/.cache/torch/hub/checkpoints/unet_r231-d5d2fc3d.pth.1’\n",
+ "\n",
+ "unet_r231-d5d2fc3d. 100%[===================>] 118.58M 201MB/s in 0.6s \n",
+ "\n",
+ "2024-01-26 19:59:36 (201 MB/s) - ‘/root/.cache/torch/hub/checkpoints/unet_r231-d5d2fc3d.pth.1’ saved [124340403/124340403]\n",
+ "\n",
+ "--2024-01-26 19:59:36-- https://github.com/JoHof/lungmask/releases/download/v0.0/unet_ltrclobes-3a07043d.pth\n",
+ "Resolving github.com (github.com)... 140.82.112.4\n",
+ "Connecting to github.com (github.com)|140.82.112.4|:443... connected.\n",
+ "HTTP request sent, awaiting response... 302 Found\n",
+ "Location: https://objects.githubusercontent.com/github-production-release-asset-2e65be/224678136/3dee2300-517d-11ea-9549-dcebe47e3998?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240126T185936Z&X-Amz-Expires=300&X-Amz-Signature=8d6fc145b67541825213944a501bdfc1245eabc5d9bdcb75fa6ff9adc01f2fc7&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=224678136&response-content-disposition=attachment%3B%20filename%3Dunet_ltrclobes-3a07043d.pth&response-content-type=application%2Foctet-stream [following]\n",
+ "--2024-01-26 19:59:36-- https://objects.githubusercontent.com/github-production-release-asset-2e65be/224678136/3dee2300-517d-11ea-9549-dcebe47e3998?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAVCODYLSA53PQK4ZA%2F20240126%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240126T185936Z&X-Amz-Expires=300&X-Amz-Signature=8d6fc145b67541825213944a501bdfc1245eabc5d9bdcb75fa6ff9adc01f2fc7&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=224678136&response-content-disposition=attachment%3B%20filename%3Dunet_ltrclobes-3a07043d.pth&response-content-type=application%2Foctet-stream\n",
+ "Resolving objects.githubusercontent.com (objects.githubusercontent.com)... 185.199.109.133, 185.199.111.133, 185.199.110.133, ...\n",
+ "Connecting to objects.githubusercontent.com (objects.githubusercontent.com)|185.199.109.133|:443... connected.\n",
+ "HTTP request sent, awaiting response... 200 OK\n",
+ "Length: 124338462 (119M) [application/octet-stream]\n",
+ "Saving to: ‘/root/.cache/torch/hub/checkpoints/unet_ltrclobes-3a07043d.pth.1’\n",
+ "\n",
+ "unet_ltrclobes-3a07 100%[===================>] 118.58M 210MB/s in 0.6s \n",
+ "\n",
+ "2024-01-26 19:59:37 (210 MB/s) - ‘/root/.cache/torch/hub/checkpoints/unet_ltrclobes-3a07043d.pth.1’ saved [124338462/124338462]\n",
+ "\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Query Data from IDC\n",
+ "\n",
+ "Now that the model environment is set up, it's time to download a sample input that is applicable to this model.\n",
+ "\n",
+ "In the cell below, we use a fixed value for the `SeriesInstanceUID` of a DICOM CT series available in IDC, which is suitable for the `lungmask` model. But this is just a starting point for you, since you can use [IDC Portal](https://portal.imagingdatacommons.cancer.gov/explore) to find other samples and evaluate robustness of this model.\n"
+ ],
+ "metadata": {
+ "id": "YVvbdlAO8_g6"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "series_instance_uid = \"1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\"\n",
+ "series_download_path = \"/content/input_data\"\n",
+ "!mkdir -p $download_dir\n",
+ "idc_client.download_dicom_series(series_instance_uid, series_download_path)"
+ ],
+ "metadata": {
+ "id": "2KCrJXza9LQM",
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "outputId": "247594c4-3320-4545-d4be-fe574ebe0d5f"
+ },
+ "execution_count": 30,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "mkdir: missing operand\n",
+ "Try 'mkdir --help' for more information.\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "We can use the IDC Radiology Image Viewer to visualize the series and study of interest."
+ ],
+ "metadata": {
+ "id": "LEh8pMbPMCWK"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "query = \"\"\"\n",
+ "SELECT\n",
+ " DISTINCT(StudyInstanceUID)\n",
+ "FROM\n",
+ " index\n",
+ "WHERE\n",
+ " SeriesInstanceUID = '{}'\n",
+ "\"\"\".format(series_instance_uid)\n",
+ "\n",
+ "study_instance_uid = idc_client.sql_query(query)['StudyInstanceUID'][0]\n",
+ "\n",
+ "print(\"URL to view the entire study:\")\n",
+ "print(get_idc_viewer_url(series_instance_uid))\n",
+ "print()\n",
+ "print(\"URL to view the specific series:\")\n",
+ "print(get_idc_viewer_url(study_instance_uid, series_instance_uid))"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "oP4L7nXoMDmB",
+ "outputId": "144779d7-111c-4921-8678-4621afb75816"
+ },
+ "execution_count": 32,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "URL to view the entire study:\n",
+ "https://viewer.imaging.datacommons.cancer.gov/viewer/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\n",
+ "\n",
+ "URL to view the specific series:\n",
+ "https://viewer.imaging.datacommons.cancer.gov/viewer/1.3.6.1.4.1.32722.99.99.239341353911714368772597187099978969331?seriesInstanceUID=1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "---\n",
+ "\n",
+ "
\n",
+ "\n",
+ "Every MHub model expect the input data to be in a specific location under `/app/data/input_data`. Similarly, data generated by every MHub model is stored under `/app/data/output_data`.\n",
+ "\n",
+ "When you use Docker to run an MHub model, you will typically map local folders to these locations. For the scope of this notebook, we can either move, copy, or link the data to the input location.\n",
+ "\n",
+ "The next cell copies our test patient data that we just downloaded to the `input_data` folder under `/app/data`."
+ ],
+ "metadata": {
+ "id": "VvHK1mua06A-"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# copy databinto input folder\n",
+ "!cp -r $series_download_path app/data/input_data/"
+ ],
+ "metadata": {
+ "id": "13H--k_7teH1"
+ },
+ "execution_count": 33,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Run the MHub Model\n",
+ "\n",
+ "The only thing that is left to do is to run the MHub model\n",
+ "\n",
+ "MHub provides a simple and standard interface: `python3 -m mhubio.run`. With the `python3 -m` option, we can start a Python module `mhubio.run` that takes care of running the MHub workflow. Each MHub model has a default workflow that processes DICOM data and generates DICOM compatible data (e.g. DICOMSEG for segmentation models).\n",
+ "\n",
+ "We will show you later how to create your own custom workflows by writing a custom configuration. Different workflows can be specified using the `--workflow` argument. To run the `default` workflow, the user can simply use `--workflow default`.\n",
+ "\n",
+ "Once the workflow is finished, we can move the generated output data from the output folder `/app/data/output_data` into our content folder at `/content/data/processed`.\n",
+ "\n"
+ ],
+ "metadata": {
+ "id": "LPxKm_2W9Cmq"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "!python3 -m mhubio.run --workflow default --debug"
+ ],
+ "metadata": {
+ "id": "ru9pn_QeuGaE",
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "outputId": "89e045b2-270d-4629-b56b-4b382293f42e"
+ },
+ "execution_count": 34,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "\u001b[96m\u001b[1m Config:\u001b[0m\n",
+ "execute:\n",
+ "- DicomImporter\n",
+ "- NiftiConverter\n",
+ "- LungMaskRunner\n",
+ "- DsegConverter\n",
+ "- DataOrganizer\n",
+ "general:\n",
+ " data_base_dir: /app/data\n",
+ " description: Default configuration for LungMask (dicom in, dicom out)\n",
+ " version: 1.0\n",
+ "modules:\n",
+ " DataOrganizer:\n",
+ " targets:\n",
+ " - dicomseg:mod=seg-->[i:sid]/lungmask.seg.dcm\n",
+ " DicomImporter:\n",
+ " import_dir: sorted_data\n",
+ " meta:\n",
+ " mod: ct\n",
+ " sort_data: true\n",
+ " source_dir: input_data\n",
+ " DsegConverter:\n",
+ " body_part_examined: CHEST\n",
+ " model_name: LungMask\n",
+ " skip_empty_slices: true\n",
+ " source_segs: nifti:mod=seg:roi=*\n",
+ " LungMaskRunner:\n",
+ " batchsize: 64\n",
+ "\n",
+ "\n",
+ "\u001b[96m\u001b[1m DicomImporter:\u001b[0m\n",
+ "\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/_global]\n",
+ "├── \u001b[96mid: global\u001b[0m\n",
+ "├── \u001b[96msid: global\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DicomImporter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DicomImporter\u001b[0m\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046]\n",
+ "├── \u001b[96mid: 36d03d66-cb17-4718-998e-4b8328bddcea\u001b[0m\n",
+ "├── \u001b[96msid: 1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\u001b[0m\n",
+ "├── \u001b[95mDICOM\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/dicom] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "\n",
+ "\u001b[96m\u001b[1m NiftiConverter:\u001b[0m\n",
+ "\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/_global]\n",
+ "├── \u001b[96mid: global\u001b[0m\n",
+ "├── \u001b[96msid: global\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DicomImporter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DicomImporter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046]\n",
+ "├── \u001b[96mid: 36d03d66-cb17-4718-998e-4b8328bddcea\u001b[0m\n",
+ "├── \u001b[96msid: 1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\u001b[0m\n",
+ "├── \u001b[95mDICOM\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/dicom] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.nii.gz] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.pmconv.log] ✓\n",
+ "│ ├── \u001b[96mmod: ct\u001b[0m\n",
+ "│ └── \u001b[96mlog-task: conversion\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "\n",
+ "\u001b[96m\u001b[1m LungMaskRunner:\u001b[0m\n",
+ "\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/_global]\n",
+ "├── \u001b[96mid: global\u001b[0m\n",
+ "├── \u001b[96msid: global\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DicomImporter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DicomImporter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/LungMaskRunner.log] ✓\n",
+ "│ └── \u001b[96mmodule: LungMaskRunner\u001b[0m\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046]\n",
+ "├── \u001b[96mid: 36d03d66-cb17-4718-998e-4b8328bddcea\u001b[0m\n",
+ "├── \u001b[96msid: 1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\u001b[0m\n",
+ "├── \u001b[95mDICOM\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/dicom] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.nii.gz] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.pmconv.log] ✓\n",
+ "│ ├── \u001b[96mmod: ct\u001b[0m\n",
+ "│ └── \u001b[96mlog-task: conversion\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/model/roi1_lungs.nii.gz] ✓\n",
+ "│ ├── \u001b[96mmod: seg\u001b[0m\n",
+ "│ ├── \u001b[96mmodel: LungMask\u001b[0m\n",
+ "│ └── \u001b[96mroi: RIGHT_LUNG,LEFT_LUNG\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/model/roi2_lunglobes.nii.gz] ✓\n",
+ "│ ├── \u001b[96mmod: seg\u001b[0m\n",
+ "│ ├── \u001b[96mmodel: LungMask\u001b[0m\n",
+ "│ └── \u001b[96mroi: LEFT_UPPER_LUNG_LOBE,LEFT_LOWER_LUNG_LOBE,RIGHT_UPPER_LUNG_LOBE,RIGHT_MIDDLE_LUNG_LOBE,RIGHT_LOWER_LUNG_LOBE\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/LungMaskRunner.log] ✓\n",
+ "│ └── \u001b[96mmodule: LungMaskRunner\u001b[0m\n",
+ "\n",
+ "\u001b[96m\u001b[1m DsegConverter:\u001b[0m\n",
+ "\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/_global]\n",
+ "├── \u001b[96mid: global\u001b[0m\n",
+ "├── \u001b[96msid: global\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DicomImporter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DicomImporter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/LungMaskRunner.log] ✓\n",
+ "│ └── \u001b[96mmodule: LungMaskRunner\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DsegConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DsegConverter\u001b[0m\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046]\n",
+ "├── \u001b[96mid: 36d03d66-cb17-4718-998e-4b8328bddcea\u001b[0m\n",
+ "├── \u001b[96msid: 1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\u001b[0m\n",
+ "├── \u001b[95mDICOM\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/dicom] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.nii.gz] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.pmconv.log] ✓\n",
+ "│ ├── \u001b[96mmod: ct\u001b[0m\n",
+ "│ └── \u001b[96mlog-task: conversion\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/model/roi1_lungs.nii.gz] ✓\n",
+ "│ ├── \u001b[96mmod: seg\u001b[0m\n",
+ "│ ├── \u001b[96mmodel: LungMask\u001b[0m\n",
+ "│ └── \u001b[96mroi: RIGHT_LUNG,LEFT_LUNG\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/model/roi2_lunglobes.nii.gz] ✓\n",
+ "│ ├── \u001b[96mmod: seg\u001b[0m\n",
+ "│ ├── \u001b[96mmodel: LungMask\u001b[0m\n",
+ "│ └── \u001b[96mroi: LEFT_UPPER_LUNG_LOBE,LEFT_LOWER_LUNG_LOBE,RIGHT_UPPER_LUNG_LOBE,RIGHT_MIDDLE_LUNG_LOBE,RIGHT_LOWER_LUNG_LOBE\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/LungMaskRunner.log] ✓\n",
+ "│ └── \u001b[96mmodule: LungMaskRunner\u001b[0m\n",
+ "├── \u001b[95mDICOMSEG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/seg.dcm] ✓\n",
+ "│ └── \u001b[96mmod: seg\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/DsegConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DsegConverter\u001b[0m\n",
+ "\n",
+ "\u001b[96m\u001b[1m DataOrganizer:\u001b[0m\n",
+ "\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/_global]\n",
+ "├── \u001b[96mid: global\u001b[0m\n",
+ "├── \u001b[96msid: global\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DicomImporter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DicomImporter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/LungMaskRunner.log] ✓\n",
+ "│ └── \u001b[96mmodule: LungMaskRunner\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DsegConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DsegConverter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/_global/mhub_log/DataOrganizer.log] ✓\n",
+ "│ └── \u001b[96mmodule: DataOrganizer\u001b[0m\n",
+ ". Instance \u001b[3m\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046]\n",
+ "├── \u001b[96mid: 36d03d66-cb17-4718-998e-4b8328bddcea\u001b[0m\n",
+ "├── \u001b[96msid: 1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046\u001b[0m\n",
+ "├── \u001b[95mDICOM\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/dicom] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.nii.gz] ✓\n",
+ "│ └── \u001b[96mmod: ct\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/nifti/dicom.pmconv.log] ✓\n",
+ "│ ├── \u001b[96mmod: ct\u001b[0m\n",
+ "│ └── \u001b[96mlog-task: conversion\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/NiftiConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: NiftiConverter\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/model/roi1_lungs.nii.gz] ✓\n",
+ "│ ├── \u001b[96mmod: seg\u001b[0m\n",
+ "│ ├── \u001b[96mmodel: LungMask\u001b[0m\n",
+ "│ └── \u001b[96mroi: RIGHT_LUNG,LEFT_LUNG\u001b[0m\n",
+ "├── \u001b[95mNIFTI\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/model/roi2_lunglobes.nii.gz] ✓\n",
+ "│ ├── \u001b[96mmod: seg\u001b[0m\n",
+ "│ ├── \u001b[96mmodel: LungMask\u001b[0m\n",
+ "│ └── \u001b[96mroi: LEFT_UPPER_LUNG_LOBE,LEFT_LOWER_LUNG_LOBE,RIGHT_UPPER_LUNG_LOBE,RIGHT_MIDDLE_LUNG_LOBE,RIGHT_LOWER_LUNG_LOBE\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/LungMaskRunner.log] ✓\n",
+ "│ └── \u001b[96mmodule: LungMaskRunner\u001b[0m\n",
+ "├── \u001b[95mDICOMSEG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/seg.dcm] ✓\n",
+ "│ └── \u001b[96mmod: seg\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/DsegConverter.log] ✓\n",
+ "│ └── \u001b[96mmodule: DsegConverter\u001b[0m\n",
+ "├── \u001b[95mLOG\u001b[0m [/app/data/sorted_data/1.3.6.1.4.1.32722.99.99.298991776521342375010861296712563382046/mhub_log/DataOrganizer.log] ✓\n",
+ "│ └── \u001b[96mmodule: DataOrganizer\u001b[0m\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "# copy output\n",
+ "output_dir = \"/content/data/processed\"\n",
+ "!mkdir -p $output_dir\n",
+ "!cp -r /app/data/output_data/$series_instance_uid $output_dir"
+ ],
+ "metadata": {
+ "id": "Tfd5kw6mGKRb"
+ },
+ "execution_count": 35,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Inspect the Results\n",
+ "\n",
+ "Finally, we can interact with the data we generated in different ways.\n",
+ "\n",
+ "We can visualise the raw AI-generated segmentation masks directly in the notebook by using the utilities developed as part of the `itkwidgets` library."
+ ],
+ "metadata": {
+ "id": "rArvDENeE_Tk"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import itk\n",
+ "import SimpleITK as sitk\n",
+ "\n",
+ "from itkwidgets import view"
+ ],
+ "metadata": {
+ "id": "u2_zZMOEg8Rx",
+ "outputId": "22efcfac-9cc5-478b-e90c-c8ca137eb4d1",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 363
+ }
+ },
+ "execution_count": 36,
+ "outputs": [
+ {
+ "output_type": "error",
+ "ename": "AttributeError",
+ "evalue": "module 'numpy.linalg._umath_linalg' has no attribute '_ilp64'",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mSimpleITK\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0msitk\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mitkwidgets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mview\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/itkwidgets/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;34m\"\"\"itkwidgets: Interactive widgets to visualize images, point sets, and 3D geometry on the web.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mviewer\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mViewer\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mview\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcompare_images\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m __all__ = [\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/itkwidgets/viewer.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0muuid\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_type_aliases\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mGaussians\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mStyle\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mImage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mPointSet\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_initialization_params\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0minit_params_dict\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_method_types\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdeferred_methods\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/itkwidgets/_type_aliases.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mintegrations\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitk\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mHAVE_ITK\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mintegrations\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpytorch\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mHAVE_TORCH\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mintegrations\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvtk\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mHAVE_VTK\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/itkwidgets/integrations/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mzarr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mngff_zarr\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mto_multiscales\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mto_ngff_zarr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mto_ngff_image\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mitk_image_to_ngff_image\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mMethods\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNgffImage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mMultiscales\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/ngff_zarr/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m__about__\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0m__version__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mcli_input_to_ngff_image\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcli_input_to_ngff_image\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mconfig\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mconfig\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0mdetect_cli_io_backend\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mConversionBackend\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdetect_cli_io_backend\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/ngff_zarr/cli_input_to_ngff_image.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mzarr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mimage\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mimread\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mdaimread\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mrich\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/dask/array/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mbackends\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfft\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlib\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlinalg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moverlap\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrandom\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblockwise\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0matop\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mblockwise\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchunk_types\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mregister_chunk_type\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/dask/array/backends.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mchunk\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcore\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mArray\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m from dask.array.dispatch import (\n\u001b[1;32m 10\u001b[0m \u001b[0mconcatenate_lookup\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/dask/array/core.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mchunk\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 36\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchunk\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mgetitem\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 37\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mdask\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchunk_types\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mis_valid_array_chunk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mis_valid_chunk_type\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 38\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[0;31m# Keep einsum_lookup and tensordot_lookup here for backwards compatibility\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/dask/array/chunk_types.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 109\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 110\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 111\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 112\u001b[0m \u001b[0mregister_chunk_type\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcupy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndarray\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/cupy/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[0;31m# `cupy.sparse` is deprecated in v8\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 46\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0msparse\u001b[0m \u001b[0;31m# NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 47\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mtesting\u001b[0m \u001b[0;31m# NOQA # NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 48\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 49\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/cupy/testing/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_array\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0massert_allclose\u001b[0m \u001b[0;31m# NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_array\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0massert_array_almost_equal\u001b[0m \u001b[0;31m# NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_array\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0massert_array_almost_equal_nulp\u001b[0m \u001b[0;31m# NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_array\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0massert_array_equal\u001b[0m \u001b[0;31m# NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_array\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0massert_array_less\u001b[0m \u001b[0;31m# NOQA\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/cupy/testing/_array.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mnumpy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtesting\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mcupy\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/numpy/testing/__init__.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0m_private\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_private\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_private\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0m_assert_valid_refcount\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_gen_alignment_data\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0;34m.\u001b[0m\u001b[0m_private\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mextbuild\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;32m/usr/local/lib/python3.10/dist-packages/numpy/testing/_private/utils.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 55\u001b[0m \u001b[0mIS_PYSTON\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msys\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"pyston_version_info\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[0mHAS_REFCOUNT\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msys\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'getrefcount'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mIS_PYSTON\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 57\u001b[0;31m \u001b[0mHAS_LAPACK64\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnumpy\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinalg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_umath_linalg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_ilp64\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 58\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 59\u001b[0m \u001b[0m_OLD_PROMOTION\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_promotion_state\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'legacy'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mAttributeError\u001b[0m: module 'numpy.linalg._umath_linalg' has no attribute '_ilp64'"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "dicomseg_file = os.path.join('/content/data/processed/', f'{model_picker.value}.seg.dcm')\n",
+ "assert os.path.isfile(dicomseg_file), f\"{dicomseg_file} not found.\""
+ ],
+ "metadata": {
+ "id": "bJkBiD7DCDQA"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "nrrd_path = \"data/processed_nrrd\"\n",
+ "\n",
+ "%mkdir -p $nrrd_path\n",
+ "\n",
+ "!segimage2itkimage --inputDICOM $dicomseg_file \\\n",
+ " --outputType nrrd \\\n",
+ " --prefix segment \\\n",
+ " --outputDirectory $nrrd_path"
+ ],
+ "metadata": {
+ "id": "Hb5g3vpBFOz5"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "merged_mask = None\n",
+ "\n",
+ "# Iterate over all the .nrrd files (segments) exported by DCMQI\n",
+ "for filename in os.listdir(nrrd_path):\n",
+ " if filename.endswith(\".nrrd\"):\n",
+ " file_path = os.path.join(nrrd_path, filename)\n",
+ " mask = sitk.ReadImage(file_path)\n",
+ "\n",
+ " if merged_mask is None:\n",
+ " merged_mask = mask\n",
+ " else:\n",
+ " merged_mask = merged_mask + mask\n",
+ "\n",
+ "# Save the merged mask\n",
+ "path_to_merged_mask = os.path.join(nrrd_path, \"merged_mask.nrrd\")\n",
+ "sitk.WriteImage(merged_mask, path_to_merged_mask)"
+ ],
+ "metadata": {
+ "id": "EGkPPkGgGjJP"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "merged_mask = itk.imread(path_to_merged_mask)\n",
+ "viewer = view(label_image=merged_mask)\n",
+ "\n",
+ "viewer.set_image_gradient_opacity(0.4)\n",
+ "viewer.set_label_image_blend(0.8)\n",
+ "viewer.set_background_color([0.25,0.25,0.25])\n",
+ "viewer.set_label_image_weights([0, 1])"
+ ],
+ "metadata": {
+ "id": "IIADYEpmHXaI"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "We can also visualize the CT scan together with the segmentation labels.\n",
+ "\n",
+ "Note: this could take a little bit longer to render!"
+ ],
+ "metadata": {
+ "id": "grq_CLKvhgIJ"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "image = itk.imread(series_download_path)\n",
+ "\n",
+ "viewer = view(image, label_image=merged_mask)\n",
+ "\n",
+ "viewer.set_background_color([0.0,0.0,0.0])"
+ ],
+ "metadata": {
+ "id": "bUGMNnJ_hfqN"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "---\n",
+ "For further analysis, we can download the DICOM Series used for segmentation and the results of the MHub segmentation model we selected.\n",
+ "\n",
+ "These data can be then inspected locally with a viewer of our choice (e.g., 3DSlicer)."
+ ],
+ "metadata": {
+ "id": "yA7_604bbgoP"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "%%capture\n",
+ "\n",
+ "archive_fn = \"%s-%s.zip\"%(my_SeriesInstanceUID, model_picker.value)\n",
+ "\n",
+ "try:\n",
+ " os.remove(archive_fn)\n",
+ "except OSError:\n",
+ " pass\n",
+ "\n",
+ "!zip -j -r $archive_fn $dicomseg_file $series_download_path"
+ ],
+ "metadata": {
+ "id": "ARmBD0lHdz_2"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "filesize = os.stat(archive_fn).st_size/1024e03\n",
+ "print('Starting the download of \"%s\" (%2.1f MB)...\\n'%(archive_fn, filesize))\n",
+ "\n",
+ "files.download(archive_fn)"
+ ],
+ "metadata": {
+ "id": "8pE0X9kid0D-"
+ },
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ ""
+ ],
+ "metadata": {
+ "id": "e6fQCJ6VISk2"
+ }
+ }
+ ]
+}
\ No newline at end of file
|