{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":94147,"databundleVersionId":11390004,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# EDA: Cell Distribution\n\nThis notebook shows the distribution of abundance for each of the 35 cells, on the slice. \n\nWhy this is useful: \n- Some cell types may tend to cluster together. They could be similar cell types, or cells that interact with each other for some biological reason\n- Some spots may have a low number of cells of any type\n- How does cell abundancy varies across all slices? For example, is C1 abundant in all slices, or not?\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"import h5py\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport math\n\ndef plot_celltype_abundance(slide_name, image, spots, plots_per_line=4, show_image=False):\n    \"\"\"\n    Plot the slide image with spot overlays for cell-type abundances (C1 to C35).\n\n    Parameters:\n        slide_name (str): Name of the slide.\n        image (np.array): 2D or 3D array representing the slide image.\n        spots (np.array): Structured NumPy array containing spot information with fields:\n                          'x', 'y', 'C1', 'C2', ..., 'C35'.\n        plots_per_line (int): Number of subplots per row (default is 4).\n\n    The function creates a figure with subplots arranged in a grid and plots:\n      - The slide image as a background.\n      - A scatter overlay at spot (x, y) positions, colored by the abundance of each cell type.\n      - A common colorbar that indicates the mapping from color to abundance.\n    \"\"\"\n    # Extract the x and y coordinates from the spots array\n    x = spots[\"x\"]\n    y = spots[\"y\"]\n    num_celltypes = 35  # There are 35 cell types (C1 to C35)\n    num_rows = math.ceil(num_celltypes / plots_per_line)\n    \n    # Create a figure with a grid of subplots\n    fig, axes = plt.subplots(num_rows, plots_per_line, figsize=(plots_per_line * 3, num_rows * 3))\n    axes = axes.flatten()  # Flatten to simplify indexing\n    \n    # Loop over each cell type field from C1 to C35\n    for i in range(num_celltypes):\n        var_name = f\"C{i+1}\"  # Create field name e.g. \"C1\", \"C2\", ...\n        c_values = spots[var_name]  # Get the abundance values for this cell type\n        \n        ax = axes[i]\n        if show_image is True:\n            ax.imshow(image, aspect=\"auto\")\n        else:\n            # Manually set the axis limits to match the image dimensions\n            height, width = image.shape[:2]\n            ax.set_xlim(0, width)\n            ax.set_ylim(height, 0)  # invert y-axis to mimic image display\n\n        sc = ax.scatter(x, y, c=c_values, cmap=\"viridis\", s=2, alpha=1)\n        #sc = ax.scatter(x, y, c=c_values, cmap=\"plasma\", s=2, alpha=0.7)\n\n        ax.set_title(var_name, fontsize=8)\n        ax.axis(\"off\")\n    \n    # If there are any extra subplots (in case grid has one more cell), hide them\n    for j in range(num_celltypes, len(axes)):\n        axes[j].axis(\"off\")\n    \n    # Set an overall title for the figure\n    fig.suptitle(f\"Slide {slide_name}\", fontsize=14)\n    \n    # Add a common colorbar (using the last scatter object)\n    #fig.colorbar(sc, ax=axes.tolist(), label=\"Abundance\")\n    #fig.subplots_adjust(right=0.85)\n    #cbar_ax = fig.add_axes([0.88, 0.15, 0.03, 0.7])  # [left, bottom, width, height]\n    #fig.colorbar(sc, cax=cbar_ax, label=\"Abundance\")\n    \n    plt.tight_layout(rect=[0, 0, 1, 0.95])\n    plt.show()\n\n\ndef plot_total_abundance(slide_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=True):\n    \"\"\"\n    Plot the slide image with spot overlays where each spot's color represents \n    the total abundance of cell types C1 to C35.\n\n    Parameters:\n        slide_name (str): Name of the slide.\n        image (np.array): The slide image.\n        spots (np.array): Structured NumPy array with fields 'x', 'y', and 'C1' ... 'C35'.\n        show_colorbar (bool): Whether to display a colorbar (default True).\n        colorbar_outside (bool): If True, place the colorbar to the right of the plot.\n    \"\"\"\n    # Extract x and y coordinates from the spots array\n    x = spots[\"x\"]\n    y = spots[\"y\"]\n    \n    # Compute total abundance by summing C1 through C35 for each spot\n    total_abundance = np.zeros_like(x, dtype=float)\n    if slide_name == \"S_7\":\n        total_abundance = spots[\"Test_Set\"]\n    else:\n        for i in range(1, 36):  # Fields C1 to C35\n            total_abundance += spots[f\"C{i}\"]\n    \n    # Create a figure\n    fig, ax = plt.subplots(figsize=(6, 6))\n    if show_image is True:\n        ax.imshow(image, aspect=\"auto\")\n    else:\n        # Manually set the axis limits to match the image dimensions\n        height, width = image.shape[:2]\n        ax.set_xlim(0, width)\n        ax.set_ylim(height, 0)  # invert y-axis to mimic image display\n\n    sc = ax.scatter(x, y, c=total_abundance, cmap=\"viridis\", s=2, alpha=0.7)\n    ax.set_title(f\"Total Abundance for Slide {slide_name}\")\n    ax.axis(\"off\")\n    \n    # Add a colorbar if desired\n    if show_colorbar:\n        if colorbar_outside:\n            # Adjust the right margin to make room for the colorbar\n            fig.subplots_adjust(right=0.85)\n            cbar_ax = fig.add_axes([0.88, 0.15, 0.03, 0.7])\n            fig.colorbar(sc, cax=cbar_ax, label=\"Total Abundance\")\n        else:\n            fig.colorbar(sc, ax=ax, label=\"Total Abundance\")\n    \n    plt.tight_layout()\n    plt.show()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:05:44.422531Z","iopub.execute_input":"2025-03-26T17:05:44.422871Z","iopub.status.idle":"2025-03-26T17:05:44.438066Z","shell.execute_reply.started":"2025-03-26T17:05:44.422843Z","shell.execute_reply":"2025-03-26T17:05:44.436950Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_1\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:01:46.880443Z","iopub.execute_input":"2025-03-26T17:01:46.880832Z","iopub.status.idle":"2025-03-26T17:01:51.939611Z","shell.execute_reply.started":"2025-03-26T17:01:46.880806Z","shell.execute_reply":"2025-03-26T17:01:51.938337Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_2\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:01:51.942257Z","iopub.execute_input":"2025-03-26T17:01:51.942675Z","iopub.status.idle":"2025-03-26T17:01:56.642447Z","shell.execute_reply.started":"2025-03-26T17:01:51.942638Z","shell.execute_reply":"2025-03-26T17:01:56.641187Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_3\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:01:56.643804Z","iopub.execute_input":"2025-03-26T17:01:56.644085Z","iopub.status.idle":"2025-03-26T17:02:00.320049Z","shell.execute_reply.started":"2025-03-26T17:01:56.644059Z","shell.execute_reply":"2025-03-26T17:02:00.318963Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_4\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:00.321268Z","iopub.execute_input":"2025-03-26T17:02:00.321656Z","iopub.status.idle":"2025-03-26T17:02:04.478285Z","shell.execute_reply.started":"2025-03-26T17:02:00.321623Z","shell.execute_reply":"2025-03-26T17:02:04.477243Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_5\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:04.479528Z","iopub.execute_input":"2025-03-26T17:02:04.479893Z","iopub.status.idle":"2025-03-26T17:02:08.809236Z","shell.execute_reply.started":"2025-03-26T17:02:04.479860Z","shell.execute_reply":"2025-03-26T17:02:08.808225Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_6\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:08.810526Z","iopub.execute_input":"2025-03-26T17:02:08.810891Z","iopub.status.idle":"2025-03-26T17:02:12.264034Z","shell.execute_reply.started":"2025-03-26T17:02:08.810857Z","shell.execute_reply":"2025-03-26T17:02:12.262997Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#slice_name = \"S_7\"\n#with h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n#    image = np.array(h5file[\"images/Test\"][slice_name])\n#    spots = np.array(h5file[\"spots/Test\"][slice_name])\n#    plot_celltype_abundance(slice_name, image, spots, plots_per_line=4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:12.265096Z","iopub.execute_input":"2025-03-26T17:02:12.265405Z","iopub.status.idle":"2025-03-26T17:02:17.204591Z","shell.execute_reply.started":"2025-03-26T17:02:12.265371Z","shell.execute_reply":"2025-03-26T17:02:17.202796Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## PLotting Total Abundance","metadata":{}},{"cell_type":"code","source":"slice_name = \"S_1\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:17.205053Z","iopub.status.idle":"2025-03-26T17:02:17.205377Z","shell.execute_reply":"2025-03-26T17:02:17.205227Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_2\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:17.206266Z","iopub.status.idle":"2025-03-26T17:02:17.206774Z","shell.execute_reply":"2025-03-26T17:02:17.206577Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_3\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:17.207657Z","iopub.status.idle":"2025-03-26T17:02:17.208041Z","shell.execute_reply":"2025-03-26T17:02:17.207905Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_4\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:17.208995Z","iopub.status.idle":"2025-03-26T17:02:17.209417Z","shell.execute_reply":"2025-03-26T17:02:17.209198Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_5\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:17.210146Z","iopub.status.idle":"2025-03-26T17:02:17.210588Z","shell.execute_reply":"2025-03-26T17:02:17.210383Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_6\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Train\"][slice_name])\n    spots = np.array(h5file[\"spots/Train\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:02:17.211453Z","iopub.status.idle":"2025-03-26T17:02:17.211838Z","shell.execute_reply":"2025-03-26T17:02:17.211666Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"slice_name = \"S_7\"\nwith h5py.File(\"/kaggle/input/el-hackathon-2025/elucidata_ai_challenge_data.h5\", \"r\") as h5file:\n    image = np.array(h5file[\"images/Test\"][slice_name])\n    spots = np.array(h5file[\"spots/Test\"][slice_name])\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True)\n    plot_total_abundance(slice_name, image, spots, show_colorbar=True, colorbar_outside=True, show_image=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-26T17:05:48.967751Z","iopub.execute_input":"2025-03-26T17:05:48.968106Z","iopub.status.idle":"2025-03-26T17:05:50.572855Z","shell.execute_reply.started":"2025-03-26T17:05:48.968077Z","shell.execute_reply":"2025-03-26T17:05:50.571755Z"}},"outputs":[],"execution_count":null}]}