{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\n\n# There are two ways to load the data from the PANDA dataset:\n# Option 1: Load images using openslide\nimport openslide\n# Option 2: Load images using skimage (requires that tifffile is installed)\nimport skimage.io\n\n# General packages\nimport pandas as pd\nimport numpy as np\nimport matplotlib\nimport matplotlib.pyplot as plt\nimport PIL\nfrom IPython.display import Image, display\n\n# Plotly for the interactive viewer (see last section)\nimport plotly.graph_objs as go","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:18:01.524811Z","iopub.execute_input":"2023-04-19T14:18:01.525278Z","iopub.status.idle":"2023-04-19T14:18:01.531852Z","shell.execute_reply.started":"2023-04-19T14:18:01.52522Z","shell.execute_reply":"2023-04-19T14:18:01.53049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Location of the training images\ndata_dir = '/kaggle/input/prostate-cancer-grade-assessment/train_images'\nmask_dir = '/kaggle/input/prostate-cancer-grade-assessment/train_label_masks'\n\n# Location of training labels\ntrain_labels = pd.read_csv('/kaggle/input/prostate-cancer-grade-assessment/train.csv').set_index('image_id')","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:18:07.482778Z","iopub.execute_input":"2023-04-19T14:18:07.483213Z","iopub.status.idle":"2023-04-19T14:18:07.505912Z","shell.execute_reply.started":"2023-04-19T14:18:07.483175Z","shell.execute_reply":"2023-04-19T14:18:07.504957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Open the image (does not yet read the image into memory)\nimage = openslide.OpenSlide(os.path.join(data_dir, '005e66f06bce9c2e49142536caf2f6ee.tiff'))\n\n# Read a specific region of the image starting at upper left coordinate (x=17800, y=19500) on level 0 and extracting a 256*256 pixel patch.\n# At this point image data is read from the file and loaded into memory.\npatch = image.read_region((17800,19500), 0, (256, 256))\n\n# Display the image\ndisplay(patch)\n\n# Close the opened slide after use\nimage.close()","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:18:11.174017Z","iopub.execute_input":"2023-04-19T14:18:11.175485Z","iopub.status.idle":"2023-04-19T14:18:11.347825Z","shell.execute_reply.started":"2023-04-19T14:18:11.175421Z","shell.execute_reply":"2023-04-19T14:18:11.346744Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def print_slide_details(slide, show_thumbnail=True, max_size=(600,400)):\n    \"\"\"Print some basic information about a slide\"\"\"\n    # Generate a small image thumbnail\n    if show_thumbnail:\n        display(slide.get_thumbnail(size=max_size))\n\n    # Here we compute the \"pixel spacing\": the physical size of a pixel in the image.\n    # OpenSlide gives the resolution in centimeters so we convert this to microns.\n    spacing = 1 / (float(slide.properties['tiff.XResolution']) / 10000)\n    \n    print(f\"File id: {slide}\")\n    print(f\"Dimensions: {slide.dimensions}\")\n    print(f\"Microns per pixel / pixel spacing: {spacing:.3f}\")\n    print(f\"Number of levels in the image: {slide.level_count}\")\n    print(f\"Downsample factor per level: {slide.level_downsamples}\")\n    print(f\"Dimensions of levels: {slide.level_dimensions}\")","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:18:43.073857Z","iopub.execute_input":"2023-04-19T14:18:43.074313Z","iopub.status.idle":"2023-04-19T14:18:43.082573Z","shell.execute_reply.started":"2023-04-19T14:18:43.074272Z","shell.execute_reply":"2023-04-19T14:18:43.081153Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_slides = [\n    '005e66f06bce9c2e49142536caf2f6ee',\n    '00928370e2dfeb8a507667ef1d4efcbb',\n    '007433133235efc27a39f11df6940829',\n    '024ed1244a6d817358cedaea3783bbde',\n]\n\nfor case_id in example_slides:\n    biopsy = openslide.OpenSlide(os.path.join(data_dir, f'{case_id}.tiff'))\n    print_slide_details(biopsy)\n    biopsy.close()\n    \n    # Print the case-level label\n    print(f\"ISUP grade: {train_labels.loc[case_id, 'isup_grade']}\")\n    print(f\"Gleason score: {train_labels.loc[case_id, 'gleason_score']}\\n\\n\")","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:18:58.961613Z","iopub.execute_input":"2023-04-19T14:18:58.962061Z","iopub.status.idle":"2023-04-19T14:18:59.914187Z","shell.execute_reply.started":"2023-04-19T14:18:58.962024Z","shell.execute_reply":"2023-04-19T14:18:59.913229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"biopsy = openslide.OpenSlide(os.path.join(data_dir, '00928370e2dfeb8a507667ef1d4efcbb.tiff'))\n\nx = 5150\ny = 21000\nlevel = 0\nwidth = 512\nheight = 512\n\nregion = biopsy.read_region((x,y), level, (width, height))\ndisplay(region)","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:19:40.757894Z","iopub.execute_input":"2023-04-19T14:19:40.758359Z","iopub.status.idle":"2023-04-19T14:19:41.050103Z","shell.execute_reply.started":"2023-04-19T14:19:40.758316Z","shell.execute_reply":"2023-04-19T14:19:41.048718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x = 5140\ny = 21000\nlevel = 1\nwidth = 512\nheight = 512\n\nregion = biopsy.read_region((x,y), level, (width, height))\ndisplay(region)","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:20:12.309643Z","iopub.execute_input":"2023-04-19T14:20:12.310132Z","iopub.status.idle":"2023-04-19T14:20:12.50167Z","shell.execute_reply.started":"2023-04-19T14:20:12.310088Z","shell.execute_reply":"2023-04-19T14:20:12.500324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def print_mask_details(slide, center='radboud', show_thumbnail=True, max_size=(400,400)):\n    \"\"\"Print some basic information about a slide\"\"\"\n\n    if center not in ['radboud', 'karolinska']:\n        raise Exception(\"Unsupported palette, should be one of [radboud, karolinska].\")\n\n    # Generate a small image thumbnail\n    if show_thumbnail:\n        # Read in the mask data from the highest level\n        # We cannot use thumbnail() here because we need to load the raw label data.\n        mask_data = slide.read_region((0,0), slide.level_count - 1, slide.level_dimensions[-1])\n        # Mask data is present in the R channel\n        mask_data = mask_data.split()[0]\n\n        # To show the masks we map the raw label values to RGB values\n        preview_palette = np.zeros(shape=768, dtype=int)\n        if center == 'radboud':\n            # Mapping: {0: background, 1: stroma, 2: benign epithelium, 3: Gleason 3, 4: Gleason 4, 5: Gleason 5}\n            preview_palette[0:18] = (np.array([0, 0, 0, 0.5, 0.5, 0.5, 0, 1, 0, 1, 1, 0.7, 1, 0.5, 0, 1, 0, 0]) * 255).astype(int)\n        elif center == 'karolinska':\n            # Mapping: {0: background, 1: benign, 2: cancer}\n            preview_palette[0:9] = (np.array([0, 0, 0, 0.5, 0.5, 0.5, 1, 0, 0]) * 255).astype(int)\n        mask_data.putpalette(data=preview_palette.tolist())\n        mask_data = mask_data.convert(mode='RGB')\n        mask_data.thumbnail(size=max_size, resample=0)\n        display(mask_data)\n\n    # Compute microns per pixel (openslide gives resolution in centimeters)\n    spacing = 1 / (float(slide.properties['tiff.XResolution']) / 10000)\n    \n    print(f\"File id: {slide}\")\n    print(f\"Dimensions: {slide.dimensions}\")\n    print(f\"Microns per pixel / pixel spacing: {spacing:.3f}\")\n    print(f\"Number of levels in the image: {slide.level_count}\")\n    print(f\"Downsample factor per level: {slide.level_downsamples}\")\n    print(f\"Dimensions of levels: {slide.level_dimensions}\")","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:20:47.140005Z","iopub.execute_input":"2023-04-19T14:20:47.140462Z","iopub.status.idle":"2023-04-19T14:20:47.153716Z","shell.execute_reply.started":"2023-04-19T14:20:47.140419Z","shell.execute_reply":"2023-04-19T14:20:47.152401Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask = openslide.OpenSlide(os.path.join(mask_dir, '08ab45297bfe652cc0397f4b37719ba1_mask.tiff'))\nprint_mask_details(mask, center='radboud')\nmask.close()","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:22:04.829452Z","iopub.execute_input":"2023-04-19T14:22:04.829874Z","iopub.status.idle":"2023-04-19T14:22:04.873686Z","shell.execute_reply.started":"2023-04-19T14:22:04.82984Z","shell.execute_reply":"2023-04-19T14:22:04.872313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask = openslide.OpenSlide(os.path.join(mask_dir, '090a77c517a7a2caa23e443a77a78bc7_mask.tiff'))\nprint_mask_details(mask, center='karolinska')\nmask.close()","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:22:11.181055Z","iopub.execute_input":"2023-04-19T14:22:11.181501Z","iopub.status.idle":"2023-04-19T14:22:11.352063Z","shell.execute_reply.started":"2023-04-19T14:22:11.18146Z","shell.execute_reply":"2023-04-19T14:22:11.350852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mask = openslide.OpenSlide(os.path.join(mask_dir, '08ab45297bfe652cc0397f4b37719ba1_mask.tiff'))\nmask_data = mask.read_region((0,0), mask.level_count - 1, mask.level_dimensions[-1])\n\nplt.figure()\nplt.title(\"Mask with default cmap\")\nplt.imshow(np.asarray(mask_data)[:,:,0], interpolation='nearest')\nplt.show()\n\nplt.figure()\nplt.title(\"Mask with custom cmap\")\n# Optional: create a custom color map\ncmap = matplotlib.colors.ListedColormap(['black', 'gray', 'green', 'yellow', 'orange', 'red'])\nplt.imshow(np.asarray(mask_data)[:,:,0], cmap=cmap, interpolation='nearest', vmin=0, vmax=5)\nplt.show()\n\nmask.close()","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:22:52.801314Z","iopub.execute_input":"2023-04-19T14:22:52.801734Z","iopub.status.idle":"2023-04-19T14:22:53.347925Z","shell.execute_reply.started":"2023-04-19T14:22:52.8017Z","shell.execute_reply":"2023-04-19T14:22:53.346543Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def overlay_mask_on_slide(slide, mask, center='radboud', alpha=0.8, max_size=(800, 800)):\n    \"\"\"Show a mask overlayed on a slide.\"\"\"\n\n    if center not in ['radboud', 'karolinska']:\n        raise Exception(\"Unsupported palette, should be one of [radboud, karolinska].\")\n\n    # Load data from the highest level\n    slide_data = slide.read_region((0,0), slide.level_count - 1, slide.level_dimensions[-1])\n    mask_data = mask.read_region((0,0), mask.level_count - 1, mask.level_dimensions[-1])\n\n    # Mask data is present in the R channel\n    mask_data = mask_data.split()[0]\n\n    # Create alpha mask\n    alpha_int = int(round(255*alpha))\n    if center == 'radboud':\n        alpha_content = np.less(mask_data.split()[0], 2).astype('uint8') * alpha_int + (255 - alpha_int)\n    elif center == 'karolinska':\n        alpha_content = np.less(mask_data.split()[0], 1).astype('uint8') * alpha_int + (255 - alpha_int)\n    \n    alpha_content = PIL.Image.fromarray(alpha_content)\n    preview_palette = np.zeros(shape=768, dtype=int)\n    \n    if center == 'radboud':\n        # Mapping: {0: background, 1: stroma, 2: benign epithelium, 3: Gleason 3, 4: Gleason 4, 5: Gleason 5}\n        preview_palette[0:18] = (np.array([0, 0, 0, 0.5, 0.5, 0.5, 0, 1, 0, 1, 1, 0.7, 1, 0.5, 0, 1, 0, 0]) * 255).astype(int)\n    elif center == 'karolinska':\n        # Mapping: {0: background, 1: benign, 2: cancer}\n        preview_palette[0:9] = (np.array([0, 0, 0, 0, 1, 0, 1, 0, 0]) * 255).astype(int)\n    \n    mask_data.putpalette(data=preview_palette.tolist())\n    mask_rgb = mask_data.convert(mode='RGB')\n\n    overlayed_image = PIL.Image.composite(image1=slide_data, image2=mask_rgb, mask=alpha_content)\n    overlayed_image.thumbnail(size=max_size, resample=0)\n\n    display(overlayed_image)","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:23:40.51479Z","iopub.execute_input":"2023-04-19T14:23:40.515254Z","iopub.status.idle":"2023-04-19T14:23:40.529615Z","shell.execute_reply.started":"2023-04-19T14:23:40.515199Z","shell.execute_reply":"2023-04-19T14:23:40.528148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"slide = openslide.OpenSlide(os.path.join(data_dir, '08ab45297bfe652cc0397f4b37719ba1.tiff'))\nmask = openslide.OpenSlide(os.path.join(mask_dir, '08ab45297bfe652cc0397f4b37719ba1_mask.tiff'))\noverlay_mask_on_slide(slide, mask, center='radboud')\nslide.close()\nmask.close()","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:23:56.46888Z","iopub.execute_input":"2023-04-19T14:23:56.469315Z","iopub.status.idle":"2023-04-19T14:23:56.589915Z","shell.execute_reply.started":"2023-04-19T14:23:56.46927Z","shell.execute_reply":"2023-04-19T14:23:56.588496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"slide = openslide.OpenSlide(os.path.join(data_dir, '090a77c517a7a2caa23e443a77a78bc7.tiff'))\nmask = openslide.OpenSlide(os.path.join(mask_dir, '090a77c517a7a2caa23e443a77a78bc7_mask.tiff'))\noverlay_mask_on_slide(slide, mask, center='karolinska', alpha=0.5)\nslide.close()\nmask.close()","metadata":{"execution":{"iopub.status.busy":"2023-04-19T14:26:17.005063Z","iopub.execute_input":"2023-04-19T14:26:17.005519Z","iopub.status.idle":"2023-04-19T14:26:17.361695Z","shell.execute_reply.started":"2023-04-19T14:26:17.00548Z","shell.execute_reply":"2023-04-19T14:26:17.360323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}