From e10951d115e314b232473f34389c6a0eb1ae5c48 Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Fri, 19 Jul 2024 17:24:51 -0400 Subject: [PATCH] chore: Remove mulimodal notebook --- multimodal_registration_vizarr.ipynb | 883 --------------------------- 1 file changed, 883 deletions(-) delete mode 100644 multimodal_registration_vizarr.ipynb diff --git a/multimodal_registration_vizarr.ipynb b/multimodal_registration_vizarr.ipynb deleted file mode 100644 index 862d52b6..00000000 --- a/multimodal_registration_vizarr.ipynb +++ /dev/null @@ -1,883 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from pathlib import Path\n", - "from wsireg.wsireg import WsiReg2D" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## wsireg for multi-modal image registration of whole slide images\n", - "\n", - "First, we will initialize the graph model and add modalities. Each modality is loaded with 3\n", - "pieces of information:\n", - "* the file path to image file to be loaded\n", - "* the image spatial resolution,\n", - "* the preprocessing parameters.\n", - "\n", - "Images that are to be registered must be a single plane and\n", - "the preprocessing parameters take care of this.\n", - "\n", - "Two default processes are available:\n", - "* _FL_ : take multi-channel image and converts to single channel through maximum intensity projection\n", - "* _BF_ : assumed to be 24-bit RGB images, these are converted to a single channel by taking RGB to greyscale\n", - "then intensity is inverted so background is black and foreground is white.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# we define a project name, output directory and whether to cache\n", - "# preprocessed images when making a registration graph instance\n", - "# project name = Sample107\n", - "# output directory is same as the data\n", - "# cache_images is True, this saves time during registration and avoids unnecessary io\n", - "reg_graph = WsiReg2D(\"ExampleReg\",\"./\", cache_images=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We will add multiple image modalities (7 in total) and 6 of these will be transformed to a single target but will take different paths.\n", - "The target modality is a post-imaging mass spectrometry(IMS) autofluorescence (AF) image to which IMS data has been previously registered.\n", - "Other modalities are AF of this section before IMS, AF on a serial section prior to immunofluorescence (IF). Finally, 3 cycles\n", - "of IF on a single section." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# global target modality\n", - "# preprocessing\n", - "# ch_indicices selects certain channels\n", - "# as_uint8 bytescales data to unsigned 8 bit for memory saving\n", - "# contrast_enhance makes low contrast fluorescence images brighter for registration\n", - "# if a value in the processing dict is set to None it is skipped. These are the defaults\n", - "\n", - "reg_graph.add_modality(\n", - " \"postAF_IMS\",\n", - " \"/data/SharedData/biomic/registration/S107_postAF_IMS.tif\",\n", - " image_res=0.5,\n", - " prepro_dict={\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": None,\n", - " \"as_uint8\": True,\n", - " \"contrast_enhance\": None,\n", - " },\n", - " channel_names=[\"eGFP - Post-IMS Autofluorescence\"],\n", - " channel_colors=[\"white\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# this is an AF modality\n", - "# we select the first channel for registration\n", - "# scale intensity to uint8\n", - "# and rotate the image 180 degrees counter-clockwise using \"rot_cc\"\n", - "# very large rotations are hard to capture with intensity based registration\n", - "# therefore we use prior knowledge to add this information\n", - "\n", - "reg_graph.add_modality(\n", - " \"preAF_IMS\",\n", - " \"/data/SharedData/biomic/registration/S107_preAF_IMS.czi\",\n", - " image_res=0.65,\n", - " prepro_dict={\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": [0],\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 180,\n", - " },\n", - " channel_names=[\n", - " \"Autofluorescence - DAPI\",\n", - " \"Autofluorescence - eGFP\",\n", - " \"Autofluorescence - dsRed\",\n", - " ],\n", - " channel_colors=[\"blue\", \"green\", \"red\"],\n", - ")\n", - "\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# serial section AF\n", - "\n", - "# in addition the previous modalities pre-processing\n", - "# this modality's section is \"mirror\" to the previous and thus needs\n", - "# a coordinate flip so we use \"flip\" preprocessing and flip horizontally the image\n", - "\n", - "reg_graph.add_modality(\n", - " \"preAF_MxIF\",\n", - " \"/data/SharedData/biomic/registration/S107_preAF_MxIF.czi\",\n", - " image_res=0.65,\n", - " prepro_dict={\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": [0],\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 90,\n", - " \"flip\": \"h\",\n", - " },\n", - " channel_names=[\n", - " \"Autofluorescence - DAPI\",\n", - " \"Autofluorescence - eGFP\",\n", - " \"Autofluorescence - dsRed\",\n", - " ],\n", - " channel_colors=[\"blue\", \"green\", \"red\"],\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### PAS registration\n", - "This modality contains a histological stain with RGB pixel data that was performed on the IMS section after IMS." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# PAS stain\n", - "# here we set image_type to \"BF\"\n", - "# this will invert image intensity values so background is 0 to better match\n", - "# the other photometric qualities of the other modalities\n", - "reg_graph.add_modality(\n", - " \"PAS_IMS\",\n", - " \"/data/SharedData/biomic/registration/S107_PAS.scn\",\n", - " image_res=0.5,\n", - " prepro_dict={\n", - " \"image_type\": \"BF\",\n", - " \"ch_indices\": None,\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 90,\n", - " \"contrast_enhance\": None,\n", - " },\n", - " channel_names=[\"R\", \"G\", \"B\",],\n", - " channel_colors=[\"red\", \"green\", \"blue\"],\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "### IF registration\n", - "The multiple cycles of IF are loaded as modalities selecting their DAPI channel to achieve cell nucleus-to-nucleus\n", - "registration. However, MxIF cycle 1 (modality : MxIF_cyc1) will be registered to this sections corresponding AF image.\n", - "Because of this, we will use special preprocessing for that registration described later." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# all MxIF cycles have similar spatial pre-processing\n", - "\n", - "reg_graph.add_modality(\n", - " \"MxIF_cyc1\",\n", - " \"/data/SharedData/biomic/registration/S107_MxIF_Cyc1.czi\",\n", - " image_res=0.65,\n", - " prepro_dict={\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": [0],\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 90,\n", - " \"flip\": \"h\",\n", - " },\n", - " channel_names=[\n", - " \"DAPI - Hoechst (Nuclei)\",\n", - " \"FITC - Aquaporin 1, AQP1 (Proximal Tubules and desc. thin limb)\",\n", - " \"Cy3 - NaCl Co-transporter, NCC (Distal convoluted tubule)\",\n", - " \"Cy5 - Synaptopodin (Glomerular epithelium)\",\n", - " ],\n", - " channel_colors=[\"blue\", \"green\", \"red\", \"yellow\"],\n", - ")\n", - "\n", - "reg_graph.add_modality(\n", - " \"MxIF_cyc2\",\n", - " \"/data/SharedData/biomic/registration/S107_MxIF_Cyc2.czi\",\n", - " image_res=0.65,\n", - " prepro_dict={\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": [0],\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 90,\n", - " \"flip\": \"h\",\n", - " },\n", - " channel_names=[\n", - " \"DAPI - Hoechst (Nuclei)\",\n", - " \"FITC - Aquaporin 1, AQP1 (Proximal Tubules and desc. thin limb)\",\n", - " \"Cy3 - Tamm Horsfall protein, THP (thick limb)\",\n", - " \"Cy5 - Aquaporin 2 (collecting ducts)\",\n", - " ],\n", - " channel_colors=[\"blue\", \"green\", \"red\", \"yellow\"],\n", - ")\n", - "\n", - "reg_graph.add_modality(\n", - " \"MxIF_cyc3\",\n", - " \"/data/SharedData/biomic/registration/S107_MxIF_Cyc3.czi\",\n", - " image_res=0.65,\n", - " prepro_dict={\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": [0],\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 90,\n", - " \"flip\": \"h\",\n", - " },\n", - " channel_names=[\n", - " \"DAPI - Hoechst (Nuclei)\",\n", - " \"FITC - Laminin, gamma-1 (Basement membrane)\",\n", - " \"Cy3 - Tamm Horsfall protein, THP (thick limb)\",\n", - " \"Cy5 - EpCAM (Distal tubule and thick limb)\",\n", - " ],\n", - " channel_colors=[\"blue\", \"green\", \"red\", \"yellow\"],\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### defining the registrations (edges) of the graph\n", - "\n", - "Now we will define how modalities move through the graph. For every modality to be registered we define\n", - "three settings:\n", - "* modality to be registered\n", - "* modality to which it will be registered\n", - "* through modalities, modalities which will form the path of alignment from one image to another\n", - "* registration parameters (elastix parameters)\n", - "* whether to use special preprocessing for this particular registration\n", - "\n", - "For this case where there are serial sections, we want to define registration paths that use the best information\n", - "for alignment. For instance, we have AF images on the two serial sections so complex non-linear registration is best performed mono-modally.\n", - "The alternative would be to register the IF data directly to the AF image, where the specificty of IF would not help find commonalities between the modalities\n", - "on which to register." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# register preAF_IMS to postAF_IMS\n", - "reg_graph.add_reg_path(\n", - " \"preAF_IMS\", \"postAF_IMS\", thru_modality=None, reg_params=[\"rigid\"]\n", - ")\n", - "\n", - "\n", - "# register preAF_MxIF to postAF_IMS\n", - "# BUT go through preAF_IMS (same section)\n", - "# this will align preAF_MXiF to preAF_IMS then\n", - "# append the transformations from preAF_IMS to postAF_IMS\n", - "# in this cases we use both rigid and non-linear (\"nl\") elastix transformation models\n", - "# for default we have \"rigid\",\"affine\" and \"nl\" these work in 90% of the cases\n", - "# alternatively you can add a file path string to elastix registration parameters saved in a text file\n", - "reg_graph.add_reg_path(\n", - " \"preAF_MxIF\", \"postAF_IMS\", thru_modality=\"preAF_IMS\", reg_params=[\"rigid\", \"nl\"],\n", - ")\n", - "\n", - "# register PAS_IMS to postAF_IMS through preAF_IMS\n", - "reg_graph.add_reg_path(\n", - " \"PAS_IMS\", \"postAF_IMS\", thru_modality=\"preAF_IMS\", reg_params=[\"rigid\"],\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# here we register MxIF_cyc1 to postAF_IMS through preAF_MxIF\n", - "# the graph will find the necessary edges to follow to get from MxIF_cyc1 to postAF_IMS\n", - "# but we use special preprocessing here since the set preprocessing for MxIF_cyc1 is\n", - "# to select the DAPI nuclei channel but here we will use the maximum intensity projection\n", - "# to process the 4 channels to 1 to align to AF\n", - "# this increases the amount of texture and spatial information for registration\n", - "# as DAPI is spatially sparse in signal, compared to all channels\n", - "\n", - "reg_graph.add_reg_path(\n", - " \"MxIF_cyc1\",\n", - " \"postAF_IMS\",\n", - " thru_modality=\"preAF_MxIF\",\n", - " reg_params=[\"rigid\"],\n", - " override_prepro={\n", - " \"source\": {\n", - " \"image_type\": \"FL\",\n", - " \"ch_indices\": None,\n", - " \"as_uint8\": True,\n", - " \"rot_cc\": 90,\n", - " \"flip\": \"h\",\n", - " },\n", - " \"target\": None,\n", - " },\n", - ")\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [], - "source": [ - "# now we align MxIF cycles 2 and 3 to postAF, this time going through MxIF Cyc1\n", - "# MxIF_cyc1 goes through preAF_MxIF to preAF_IMS to postAF_IMS\n", - "reg_graph.add_reg_path(\n", - " \"MxIF_cyc2\", \"postAF_IMS\", thru_modality=\"MxIF_cyc1\", reg_params=[\"rigid\"],\n", - ")\n", - "\n", - "reg_graph.add_reg_path(\n", - " \"MxIF_cyc3\", \"postAF_IMS\", thru_modality=\"MxIF_cyc1\", reg_params=[\"rigid\"],\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "### graph information\n", - "We can use some utility functions to learn about the graph." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "number of modalities : 7\n", - "number of registrations : 6\n" - ] - } - ], - "source": [ - "print(\"number of modalities : {}\".format(reg_graph.n_modalities))\n", - "print(\"number of registrations : {}\".format(reg_graph.n_registrations))" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'preAF_IMS': ['postAF_IMS'], 'preAF_MxIF': ['preAF_IMS', 'postAF_IMS'], 'PAS_IMS': ['preAF_IMS', 'postAF_IMS'], 'MxIF_cyc1': ['preAF_MxIF', 'postAF_IMS'], 'MxIF_cyc2': ['MxIF_cyc1', 'postAF_IMS'], 'MxIF_cyc3': ['MxIF_cyc1', 'postAF_IMS']}\n" - ] - } - ], - "source": [ - "print(reg_graph.reg_paths)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'preAF_IMS': [{'source': 'preAF_IMS', 'target': 'postAF_IMS'}], 'preAF_MxIF': [{'source': 'preAF_MxIF', 'target': 'preAF_IMS'}, {'source': 'preAF_IMS', 'target': 'postAF_IMS'}], 'PAS_IMS': [{'source': 'PAS_IMS', 'target': 'preAF_IMS'}, {'source': 'preAF_IMS', 'target': 'postAF_IMS'}], 'MxIF_cyc1': [{'source': 'MxIF_cyc1', 'target': 'preAF_MxIF'}, {'source': 'preAF_MxIF', 'target': 'preAF_IMS'}, {'source': 'preAF_IMS', 'target': 'postAF_IMS'}], 'MxIF_cyc2': [{'source': 'MxIF_cyc2', 'target': 'MxIF_cyc1'}, {'source': 'MxIF_cyc1', 'target': 'preAF_MxIF'}, {'source': 'preAF_MxIF', 'target': 'preAF_IMS'}, {'source': 'preAF_IMS', 'target': 'postAF_IMS'}], 'MxIF_cyc3': [{'source': 'MxIF_cyc3', 'target': 'MxIF_cyc1'}, {'source': 'MxIF_cyc1', 'target': 'preAF_MxIF'}, {'source': 'preAF_MxIF', 'target': 'preAF_IMS'}, {'source': 'preAF_IMS', 'target': 'postAF_IMS'}]}\n" - ] - } - ], - "source": [ - "# show all transformation paths\n", - "print(reg_graph.transform_paths)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'source': 'MxIF_cyc1', 'target': 'preAF_MxIF'}\n", - "{'source': 'preAF_MxIF', 'target': 'preAF_IMS'}\n", - "{'source': 'preAF_IMS', 'target': 'postAF_IMS'}\n" - ] - } - ], - "source": [ - "# look at how MxIF_cyc3 will be transformed specifically\n", - "print(*reg_graph.transform_paths[\"MxIF_cyc1\"], sep=\"\\n\")\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "pycharm": { - "name": "#%% md\n" - } - }, - "source": [ - "From the above we can see a list of transformations that will be applied to transform MxIF_cyc1 to\n", - "postAF_IMS.\n", - "\n", - "### executing the graph\n", - "Now we have loaded and set all registration modalities, we can begin the alignment and transformation process." - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "performing preprocessing: max_int_proj\n", - "cannot perform maximum intensity project on single channel image\n", - "performing preprocessing: contrast_enhance\n", - "performing preprocessing: max_int_proj\n", - "cannot perform maximum intensity project on single channel image\n", - "no inversions to compute\n", - "performing preprocessing: max_int_proj\n", - "cannot perform maximum intensity project on single channel image\n", - "performing preprocessing: contrast_enhance\n", - "no inversions to compute\n", - "performing preprocessing: inv_int\n", - "no inversions to compute\n", - "performing preprocessing: max_int_proj\n", - "performing preprocessing: contrast_enhance\n", - "no inversions to compute\n", - "performing preprocessing: max_int_proj\n", - "cannot perform maximum intensity project on single channel image\n", - "performing preprocessing: contrast_enhance\n", - "performing preprocessing: max_int_proj\n", - "cannot perform maximum intensity project on single channel image\n", - "performing preprocessing: contrast_enhance\n", - "no inversions to compute\n", - "performing preprocessing: max_int_proj\n", - "cannot perform maximum intensity project on single channel image\n", - "performing preprocessing: contrast_enhance\n", - "no inversions to compute\n" - ] - } - ], - "source": [ - "# align images, this can take some time depending on computer performance\n", - "# generally 3-10 minutes per registration when using the default models\n", - "reg_graph.register_images()\n" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "# save the transformations as a json on disk (can be reloaded and used again)\n", - "reg_graph.save_transformations()" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "pycharm": { - "name": "#%%\n" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "transforming preAF_IMS to postAF_IMS\n", - "transforming preAF_MxIF to postAF_IMS\n", - "transforming PAS_IMS to postAF_IMS\n", - "transforming MxIF_cyc1 to postAF_IMS\n", - "transforming MxIF_cyc2 to postAF_IMS\n", - "transforming MxIF_cyc3 to postAF_IMS\n", - "warning: not all edges have been registered, skipping transformation of registered images\n", - "transforming non-registered modality : postAF_IMS \n" - ] - } - ], - "source": [ - "# transform and save images to disk as zarr directory stores for remote viewing\n", - "# this function returns a list of file paths to the zarr stores created during transformation\n", - "# this list can then be passed into vizarr\n", - "zarr_fps = reg_graph.transform_images(file_writer=\"zarr\")" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Vizarr Imjoy Plugin setup\n", - "\n", - "For more details, please see: https://github.com/hms-dbmi/vizarr" - ], - "metadata": { - "collapsed": false, - "pycharm": { - "name": "#%% md\n" - } - } - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING:JupyterConnection:Removing duplicated codec: zarr-array\n", - "WARNING:JupyterConnection:Removing duplicated codec: zarr-group\n" - ] - } - ], - "source": [ - "from imjoy import api\n", - "import zarr\n", - "\n", - "def encode_zarr_store(zobj):\n", - " def getItem(key):\n", - " return zobj.store[key]\n", - "\n", - " def setItem(key, value):\n", - " zobj.store[key] = value\n", - "\n", - " def containsItem(key):\n", - " if key in zobj.store:\n", - " return True\n", - "\n", - " return {\n", - " \"_rintf\": True,\n", - " \"_rtype\": 'zarr-array' if isinstance(zobj, zarr.Array) else 'zarr-group',\n", - " \"getItem\": getItem,\n", - " \"setItem\": setItem,\n", - " \"containsItem\": containsItem,\n", - " }\n", - "\n", - "api.registerCodec({'name': 'zarr-array', 'type': zarr.Array, \"encoder\": encode_zarr_store})\n", - "api.registerCodec({'name': 'zarr-group', 'type': zarr.Group, \"encoder\": encode_zarr_store})\n", - "\n", - "class VivPlugin:\n", - " def __init__(self, images):\n", - " if not isinstance(images, list):\n", - " images = [images]\n", - " self.images = images\n", - "\n", - " async def setup(self):\n", - " pass\n", - "\n", - " async def run(self, ctx):\n", - " viewer = await api.createWindow(\n", - " type=\"vizarr\",\n", - " src=\"https://hms-dbmi.github.io/vizarr/\"\n", - " )\n", - " for img in self.images:\n", - " await viewer.add_image(img)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def run_vizarr(image):\n", - " api.export(VivPlugin(image))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## gather the data for vizarr" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [], - "source": [ - "registered_images = [\n", - " {\n", - " \"source\": zarr.open(zfp),\n", - " \"name\": Path(zfp).stem.replace(\"ExampleReg-\", \"\").split(\"_to\")[0],\n", - " }\n", - " for zfp in zarr_fps\n", - "]\n" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "window.connectPlugin && window.connectPlugin()" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "run_vizarr(registered_images)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## check how nuclei overlay accross MxIF cycles\n", - "Examine only the DAPI stains of the MxIF images to see nuclear overlap." - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [], - "source": [ - "import json\n", - "from zarr.util import json_dumps\n", - "\n", - "class StackedOMEStore:\n", - " def __init__(self, z_grps, axis=0):\n", - " self.z_grps = z_grps\n", - " self._stack_axis = axis\n", - " self._proxy_meta = self._create_proxy_meta()\n", - "\n", - " def __getitem__(self, key):\n", - " if key.endswith(\".zarray\"):\n", - " return self._proxy_meta[key]\n", - "\n", - " if key.endswith(\".zgroup\") or key.endswith(\".zattrs\"):\n", - " # let first store handle all other requests for metadata\n", - " return self.z_grps[0].store[key]\n", - "\n", - " # Should just be multiscale pattern now\n", - " # Probably a better way to do this...\n", - " path = Path(key)\n", - " ckeys = path.name.split(\".\")\n", - " z_grp_key = int(ckeys[self._stack_axis])\n", - " zgrp = self.z_grps[z_grp_key]\n", - "\n", - " ckeys[self._stack_axis] = \"0\" # change key to zero in underling store\n", - " return zgrp.store[str(path.parent / \".\".join(ckeys))]\n", - "\n", - " def __setitem__(self, key, value):\n", - " raise NotImplementedError()\n", - "\n", - " def _create_proxy_meta(self):\n", - " proxy = dict()\n", - " grp = self.z_grps[0]\n", - " for d in grp.attrs[\"multiscales\"][0][\"datasets\"]:\n", - " path = f\"{d['path']}/.zarray\"\n", - " b = grp.store[path]\n", - " arr_meta = json.loads(b)\n", - " arr_meta[\"shape\"][self._stack_axis] = len(self.z_grps)\n", - " proxy[path] = json_dumps(arr_meta)\n", - " return proxy\n", - "\n", - " def __iter__(self):\n", - " for key in self.z_grps[0].store:\n", - " yield key\n", - "\n", - "# get MxIF data\n", - "dapi_grps = [zarr.open(zfp)\n", - " for zfp in zarr_fps if \"MxIF_cyc\" in Path(zfp).stem\n", - "]\n", - "\n", - "# stack MxIF images along first axis\n", - "dapi_stack = zarr.open(StackedOMEStore(dapi_grps, axis=0))\n", - "\n", - "# prepare for vizarr with specific channel names\n", - "dapi_registered = { \"source\": dapi_stack, \n", - " \"channel_axis\": 0,\n", - " \"name\":\"DAPI merged\",\n", - " \"names\": [\"DAPI Cycle 1\", \"DAPI Cycle 2\", \"DAPI Cycle 3\"], \n", - " \n", - " }" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "data": { - "application/javascript": [ - "window.connectPlugin && window.connectPlugin()" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "run_vizarr(dapi_registered)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "wsireg\n", - "language": "python", - "name": "wsireg" - }, - "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.8.3" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} \ No newline at end of file