{ "cells": [ { "cell_type": "markdown", "id": "a309d4a5-314d-4937-b8b8-7049534f1409", "metadata": {}, "source": [ "# Image Processing\n", "\n", "Start from this notebook before doing the others in this folder! The other notebooks depend on the directory structure set up in this one." ] }, { "cell_type": "code", "execution_count": 1, "id": "c5402f37-a684-4c1b-8efc-446448b027e3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The PalmettoBUG package is copyrighted 2024-2025 by the Medical University of South Carolina and licensed under the GPL-3 license.\n", "It is free & open source software, can be redistributed in compliance with the GPL3 license, and comes with absolutely no warranty.\n", "In python, use palmettobug.print_license() to see the license, or use palmettobug.print_3rd_party_license_info() to print information\n", "about the licenses and copyright of 3rd party software used in PalmettoBUG itself or in the creation of PalmettoBUG.\n" ] } ], "source": [ "import os\n", "from pathlib import Path\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "import seaborn.objects as so\n", "import seaborn as sns\n", "\n", "import tifffile as tf\n", "\n", "import palmettobug as pbug" ] }, { "cell_type": "code", "execution_count": 2, "id": "7ed8d69b-0a9c-4b16-b252-7af970cafea7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'0.2.11'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pbug.__version__" ] }, { "cell_type": "markdown", "id": "3c480167-7ac3-4374-9406-8b5d28017181", "metadata": {}, "source": [ "### CHANGE The following directory to match an existing directory on your computer if you are testing this tutorial on your own machine!" ] }, { "cell_type": "code", "execution_count": 3, "id": "10bfcaaa-6887-4a24-b3a1-e93d332abd7f", "metadata": {}, "outputs": [], "source": [ "my_computer_path = \"C:/Users/Default/Desktop\" ## CHANGE This DIRECTORY to match an existing directory on your computer if you are testing this tutorial on your own machine!" ] }, { "cell_type": "markdown", "id": "a2751a42-d530-408b-ad0f-90d67ca742ce", "metadata": {}, "source": [ "## Set up a new directory and project\n", "\n", "Here we:\n", "\n", " 1). Set up a fresh directory on our computer that we wll place the project\n", "\n", " 2). fetch the example data from PalmettoBUG into the project directory\n", "\n", " 3). load the directory into a pbug.ImageAnalysis object" ] }, { "cell_type": "code", "execution_count": 4, "id": "a0081295-9de6-45b7-be7b-17f059ad779e", "metadata": {}, "outputs": [], "source": [ "# pbug.fetch_IMC_example(my_computer_path) ## this only needs to be run once\n", " ## Alternatively, you can download and extract the example data directly from Zenodo\n", " ## which is likely faster and more stable! However, if you do download directly\n", " ## from Zenodo, be sure that the directory path you supply in the line below is correct!\n", "project_directory = my_computer_path + \"/Example_IMC\"" ] }, { "cell_type": "code", "execution_count": 5, "id": "b782fb63-d4bc-44ab-8d21-9d8a920c87ec", "metadata": {}, "outputs": [], "source": [ "resolutions = [1.0, 1.0] ## in micrometers. 1 micron is standard IMC resolution\n", "ImageAnalysis = pbug.imc_entrypoint(project_directory, resolutions = resolutions, from_mcds = True) ## The example data is available as .tiff files, because the mcd files are too large to bundle with the program easily." ] }, { "cell_type": "markdown", "id": "f4b55494-1eb5-444a-81b7-43a582323e1e", "metadata": {}, "source": [ "## Next, set up the panel file:" ] }, { "cell_type": "code", "execution_count": 6, "id": "40fa1537-2135-4b79-a7f6-7ef3f7b28286", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
channelnamekeepsegmentation
0I127127I0NaN
1Xe131131Xe0NaN
2Ba132132Ba0NaN
3Ba138138Ba0NaN
4Pr141aSMA1NaN
5Nd142p-selectin1NaN
6Nd143Vimentin1NaN
7Nd144CD141NaN
8Nd145CD311NaN
9Nd146CD161NaN
10Nd148Pan-Keratin1NaN
11Sm149CD11b1NaN
12Eu151CD1631NaN
13Sm152CD451NaN
14Eu153CD2061NaN
15Sm154CCL21NaN
16Gd155FoxP31NaN
17Gd156CD41NaN
18Gd158E-cadherin1NaN
19Tb159CD681NaN
20Gd160CD66b1NaN
21Dy161CD201NaN
22Dy162CD81NaN
23Dy163Vitrionectin1NaN
24Dy164CD32b1NaN
25Er167GranzymeB1NaN
26Er168Ki-671NaN
27Tm169Collagen-11NaN
28Er170CD31NaN
29Yb171HistoneH311.0
30Yb172Beta-Catenin1NaN
31Yb173CD45RO1NaN
32Yb174HLA-DR1NaN
33BCKG190190BCKG0NaN
34Ir191DNA111.0
35Ir193DNA211.0
36Pt195Seg112.0
37Pt196Seg212.0
38Pt198Seg312.0
\n", "
" ], "text/plain": [ " channel name keep segmentation\n", "0 I127 127I 0 NaN\n", "1 Xe131 131Xe 0 NaN\n", "2 Ba132 132Ba 0 NaN\n", "3 Ba138 138Ba 0 NaN\n", "4 Pr141 aSMA 1 NaN\n", "5 Nd142 p-selectin 1 NaN\n", "6 Nd143 Vimentin 1 NaN\n", "7 Nd144 CD14 1 NaN\n", "8 Nd145 CD31 1 NaN\n", "9 Nd146 CD16 1 NaN\n", "10 Nd148 Pan-Keratin 1 NaN\n", "11 Sm149 CD11b 1 NaN\n", "12 Eu151 CD163 1 NaN\n", "13 Sm152 CD45 1 NaN\n", "14 Eu153 CD206 1 NaN\n", "15 Sm154 CCL2 1 NaN\n", "16 Gd155 FoxP3 1 NaN\n", "17 Gd156 CD4 1 NaN\n", "18 Gd158 E-cadherin 1 NaN\n", "19 Tb159 CD68 1 NaN\n", "20 Gd160 CD66b 1 NaN\n", "21 Dy161 CD20 1 NaN\n", "22 Dy162 CD8 1 NaN\n", "23 Dy163 Vitrionectin 1 NaN\n", "24 Dy164 CD32b 1 NaN\n", "25 Er167 GranzymeB 1 NaN\n", "26 Er168 Ki-67 1 NaN\n", "27 Tm169 Collagen-1 1 NaN\n", "28 Er170 CD3 1 NaN\n", "29 Yb171 HistoneH3 1 1.0\n", "30 Yb172 Beta-Catenin 1 NaN\n", "31 Yb173 CD45RO 1 NaN\n", "32 Yb174 HLA-DR 1 NaN\n", "33 BCKG190 190BCKG 0 NaN\n", "34 Ir191 DNA1 1 1.0\n", "35 Ir193 DNA2 1 1.0\n", "36 Pt195 Seg1 1 2.0\n", "37 Pt196 Seg2 1 2.0\n", "38 Pt198 Seg3 1 2.0" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display(ImageAnalysis.panel)" ] }, { "cell_type": "code", "execution_count": 7, "id": "9427d15c-fc3a-47fb-be63-95b143747089", "metadata": {}, "outputs": [], "source": [ "## The PalmettoBUG GUI does this automatically, but we need to convert the string representations of \"nuclei\"\n", "## and \"Cytoplasmic / Membrane\" to numbers (1 and 2, repectively). \n", "\n", "ImageAnalysis.panel.loc[[29,34,35],\"segmentation\"] = 1.0\n", "ImageAnalysis.panel.loc[36:,\"segmentation\"] = 2.0" ] }, { "cell_type": "code", "execution_count": 8, "id": "18043944-0a33-4174-b5e1-b50e781b9fab", "metadata": {}, "outputs": [], "source": [ "'''\n", "Seeing the panel with the keep == 0 channels dropped is useful, as this will be the order of the channels in the .tiff files in /images/img, and therefore\n", "the actual order of channels expected by certain steps of the program (such as pixel classification) when dealing with the images.\n", " # Uncomment line below to see the panel with only kept channels\n", "'''\n", "display()\n", "# ImageAnalysis.panel[ImageAnalysis.panel['keep'] == 1].reset_index().drop('index', axis = 1)" ] }, { "cell_type": "code", "execution_count": 9, "id": "4f075069-ec12-421e-b85a-aacfb1382adb", "metadata": {}, "outputs": [], "source": [ "### The panel needs to be exported to the disc for record keeping, for loading the segmentation / denoiser ImageAnalysis class, and for reloading from the same directory with the same panel settings\n", "ImageAnalysis.panel_write() ## not needed if using a TableLaunch GUI to enter panel file values" ] }, { "cell_type": "markdown", "id": "e81090fa-db49-41e5-be11-b0290b082327", "metadata": {}, "source": [ "## Now we can convert the /raw files to image files\n", "\n", "This step does 4 things:\n", "\n", " 1). Moves data from the /raw folder in the project directory --> to the /images/img folder\n", " \n", " 2). If starting from MCDs, unpacks 1 .ome.tiff file in /images/img for every ROI in the MCDs\n", "\n", " 3). If hpf > 0, performs hot pixel filtering (see steinbock hot pixel filtering for what this does) to each image exported to /images/img\n", "\n", " 4). Only exports channels with keep == 1 in the panel file" ] }, { "cell_type": "code", "execution_count": 10, "id": "cd3bd0b8-fc63-46ff-b0a9-663977b517b8", "metadata": {}, "outputs": [], "source": [ "## convert MCDs ---> ome.tiff files. \n", " ## with from_mcds = False, would convert Tiff --> ome.tiff, with the primary purpose being to hot pixel filter & to drop channels with keep = 0 in the panel file\n", "ImageAnalysis.raw_to_img(hpf = 0.85) # hpf = 50 is the default from steinbock\n", "\n", "## do not worry about \"Key not found: list index out of range\" messages -- this is normal " ] }, { "cell_type": "markdown", "id": "a0d6bcec-3082-4b9d-8408-4fbaad3e4919", "metadata": {}, "source": [ "## Segmentation \n", "\n", "Because DeepCell-derived masks are already available in the Example Data, segmentation, etc. are not necessary in this notebook.\n", "\n", "For extra-strict compliance with GPL3, the segmentation & denoising tutorials are covered in the documentation for isoSegDenoise, see the following links:\n", " \n", "- DeepCell segmentation: https://isosegdenoise.readthedocs.io/en/latest/notebooks/ImageSegmentation.html\n", " \n", "- Cellpose segmentation, denoising options, & mask expansion: https://isosegdenoise.readthedocs.io/en/latest/notebooks/MoreImageProcessingOptions.html" ] }, { "cell_type": "markdown", "id": "618b81b8-18da-4104-989e-a1f69f9368eb", "metadata": {}, "source": [ "## Next make region measurements from the Segmentation masks.\n", "\n", "This requires:\n", "\n", " 1). an Analysis directory must be set up. This is a folder structure where the later Single-cell Analysis can be conducted.\n", " There can be multiple Analyses per one project (if, say, you were testing whether or not denoising certain channels made a \n", " difference to the analysis, you could have a separate Analysis for each), so they are by default placed in the /Analyses folder\n", " of the project directory, only needing a unique folder name to be provided.\n", "\n", " 2). The folder of images to make measurements off of (input_img_folder)\n", " \n", " 3). The folder of segmentation masks to define the regions where measurements will be taken (input_mask_folder)\n", "\n", " 4). The aggregate statistic to use on the values of the channels in the regions, such mean or median.\n", "\n", " 5). The output folder for the intensities csv and the regionprops csvs (output_intensities_folder and output_regions_folder).\n", "\n", " -- These csv's are the same / similar as from steinbock's region measurement steps (on which this was derived)\n", " One csv of each type is generated for every image in the input_img_folder\n", " \n", " -- The intensities csv's contain the aggregate intensity of each channel within each segmentation region\n", "\n", " -- The regionprops csv's contain details about the segmentation masks, such as details related to the shape and\n", " location of each mask. \n", "\n", "While the input and output folders typically follow a set structure -- as they do in this example as well as in the GUI -- there is no theoretical restriction\n", "on where you could input images / masks from or write them to, so there is flexbility in how this can be used. " ] }, { "cell_type": "code", "execution_count": 11, "id": "42fd306e-e2cd-4bf0-bfc8-16484a8cfa7b", "metadata": {}, "outputs": [], "source": [ "''' Name and setup the Analysis directory '''\n", "\n", "analysis_folder_name = \"MyAmazingAnalysis\"\n", "ImageAnalysis.directory_object.make_analysis_dirs(analysis_folder_name)" ] }, { "cell_type": "code", "execution_count": 12, "id": "0d6ad3a7-31cc-47aa-bba8-5882476ec441", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CRC_1_ROI_001.ome intensities csv has been written!\n", "CRC_1_ROI_002.ome intensities csv has been written!\n", "CRC_2_ROI_001.ome intensities csv has been written!\n", "CRC_2_ROI_002.ome intensities csv has been written!\n", "CRC_2_ROI_003.ome intensities csv has been written!\n", "CRC_2_ROI_004.ome intensities csv has been written!\n", "CRC_3_ROI_001.ome intensities csv has been written!\n", "CRC_3_ROI_002.ome intensities csv has been written!\n", "CRC_3_ROI_003.ome intensities csv has been written!\n", "CRC_3_ROI_004.ome intensities csv has been written!\n", "CRC_1_ROI_001.ome regions csv has been written!\n", "CRC_1_ROI_002.ome regions csv has been written!\n", "CRC_2_ROI_001.ome regions csv has been written!\n", "CRC_2_ROI_002.ome regions csv has been written!\n", "CRC_2_ROI_003.ome regions csv has been written!\n", "CRC_2_ROI_004.ome regions csv has been written!\n", "CRC_3_ROI_001.ome regions csv has been written!\n", "CRC_3_ROI_002.ome regions csv has been written!\n", "CRC_3_ROI_003.ome regions csv has been written!\n", "CRC_3_ROI_004.ome regions csv has been written!\n" ] } ], "source": [ "'''\n", "Make measurements of the segmented / masked regions\n", "'''\n", "\n", "input_img_folder = ImageAnalysis.directory_object.img_dir + \"/img\"\n", "input_mask_folder = ImageAnalysis.directory_object.masks_dir + \"/example_deepcell_masks\" ## this replicates the masks perfectly (from a tensorflow-based \n", " ## segmentation) to match the example data\n", " ## change to ImageAnalysis.directory_object.masks_dir + \"/deepcell\"\n", " ## in order to use the masks we created in the preceding cells\n", " ## these may not perfectly match the example masks due to differences \n", " ## in GPU rounding / system architecture, torch vs tensorflow, etc.\n", "output_intensities_folder = ImageAnalysis.directory_object.intensities_dir # (default)\n", "output_regions_folder = ImageAnalysis.directory_object.regionprops_dir # (default)\n", "\n", "\n", "statistic_options = [\"sum\", \"min\", \"max\", \"mean\",\"median\",\"std\",\"var\"]\n", "statistic = \"mean\" ## this is the default, and rarely would you want to deviate from this\n", "\n", "re_do = True ## Determines if existing .csv's in the outputs folder wil be redone / overwritten or not. Naturally, this does not matter the first thme it is run.\n", "\n", "ImageAnalysis.make_segmentation_measurements(input_img_folder, \n", " input_mask_folder, \n", " statistic = statistic, \n", " re_do = re_do, \n", " output_intensities_folder = output_intensities_folder, \n", " output_regions_folder = output_regions_folder)" ] }, { "cell_type": "markdown", "id": "477b3c37-c4b3-4c7c-b82d-9271a6e72efb", "metadata": {}, "source": [ "## Next, make the panel and metadata files for the Analysis\n", "\n", "Preliminary panel and metadata can be easily generated with the to_analysis method, but will still need to be edited for actual use in a Single cell analysis.\n", "\n", "Data that can't be automatically supplied by this method include:\n", "\n", " 1). metadata --> patient_id and condition columns must be supplied by the user\n", "\n", " 2). Analysis_panel --> marker_class (type, state, none)\n", "\n", "However, in this case the example data comes bundled with a fully set-up analysis panel and metadata file, you we don't need to provide this information." ] }, { "cell_type": "markdown", "id": "97ae738c-2721-416a-912b-15a7e5407074", "metadata": {}, "source": [ "## Note: These cells will create 2 pop-up windows to assist you in editing the metadata / panel files! \n", "\n", "If you want to replicate the documentation, click Accept and Return without making any edits in the pop up windows\n", "\n", "If the pop up is too large (you can't see the bottom button), close the window, reduce the height value and try again." ] }, { "cell_type": "code", "execution_count": 13, "id": "75be7aae-6069-4c61-b0ef-aa0c6898c8d4", "metadata": {}, "outputs": [], "source": [ "'''\n", "Now, generate preliminary metadata / Analysis panel files -- if you have not created them already in another program like excel -- then edit\n", "'''\n", "panel, metadata, panel_path, metadata_path = ImageAnalysis.to_analysis(metadata_from_save = True) ## we set metadata_from_save to True because of how the example is loaded from the package.\n", "\n", "## Uncomment to show the intial panels:\n", "# display(metadata)\n", "# display(panel)" ] }, { "cell_type": "code", "execution_count": 18, "id": "f0690b83-6d9f-4df2-a337-e02970e29fb2", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [ "'''TableLaunches supply as easy & intuitive way to edit the preliminary versions of these files:'''\n", "export_path = panel_path\n", "pbug.TableLaunch(dataframe = panel, table_type = \"Analysis_panel\", export_path = export_path,\n", " labels_editable = True, width = 1.5, height = 0.5).mainloop()\n", "\n", "export_path = metadata_path\n", "pbug.TableLaunch(dataframe = metadata, table_type = \"metadata\", export_path = export_path,\n", " labels_editable = True, width = 1.5, height = 0.9).mainloop()\n", "\n", "'''However, these files are already set up and do not need to be edited further, unless desired to test out the affects of different settings)'''\n", "display()" ] }, { "cell_type": "markdown", "id": "43afa303-6804-44cc-b938-cff80cd0433e", "metadata": {}, "source": [ "## Load the analysis directory into the PalmettoBUG.Analysis class to begin Single-cell analysis" ] }, { "cell_type": "code", "execution_count": 15, "id": "241962db-1944-4b0d-9403-24781d5be703", "metadata": {}, "outputs": [], "source": [ "'''\n", "Now that the proper analysis directory strucutre has been made and populated with .fcs files and the metadata and panel files, we can initiate an analysis\n", "'''\n", "\n", "Analysis_experiment = pbug.Analysis()\n", "Analysis_experiment.load_data(ImageAnalysis.directory_object.Analysis_internal_dir) ## Note how the directory here is the \"internal_dir\" \n", "#Analysis_experiment.load_fcs() # --> in your system's file explorer you see this as the \"/main\" folder inside the analysis folder" ] }, { "cell_type": "code", "execution_count": 16, "id": "64efe684-1d02-4129-9256-f733442a1fe6", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'''\n", "Doing a single-cell data analysis in PalmettoBUG will be covered more in a different notebook -- but for this notebook I will generate a countplot just to show that\n", "we have successfully entered the Analysis portion of the software!\n", "'''\n", "fig = Analysis_experiment.plot_cell_counts(group_by = \"sample_id\", color_by = \"condition\", filename = \"countplot.png\")\n", "fig" ] }, { "cell_type": "code", "execution_count": null, "id": "25e5ded6-a1d8-44e5-a344-d4d12238fd30", "metadata": { "editable": true, "slideshow": { "slide_type": "" }, "tags": [] }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.16" } }, "nbformat": 4, "nbformat_minor": 5 }