From b90f049a7f0f016f4bcf2cfa4462705d505aa5dc Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Fri, 20 Dec 2024 17:53:03 -0500 Subject: [PATCH 1/2] COMP: Change binder Qt dep from PyQt5 QtPy to PySide2 PySid2 is licensed under the LGPL while PyQt5 is under the GPL and a commercial license. I could not successfully install the previous PyQt5 given versions on Linux with Python 3.11. --- .binder/requirements.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.binder/requirements.txt b/.binder/requirements.txt index 2b31e4b7..f5d15858 100644 --- a/.binder/requirements.txt +++ b/.binder/requirements.txt @@ -8,8 +8,6 @@ numpy torch>=2.0 monai>=1.2.0 matplotlib==3.3.1 -PyQt5==5.15.0 -PyQt5-sip==12.8.0 -QtPy==1.9.0 +PySide2 voila tqdm From c1612c62972884e22feadc45bc7f6bfa488abe53 Mon Sep 17 00:00:00 2001 From: Matt McCormick Date: Fri, 20 Dec 2024 18:11:47 -0500 Subject: [PATCH 2/2] DOC: Add OME-Zarr image registration notebook A simple example that registers one timepoint in an IDR dataset to another. We use the IDR dataset as it is a familiar reference sample OME-Zarr dataset in the community. This also demonstrates fetching the data dynamically from the cloud. --- .binder/requirements.txt | 1 + .gitignore | 1 + examples/ITK_Example23_OMEZarr.ipynb | 561 +++++++++++++++++++++++++++ 3 files changed, 563 insertions(+) create mode 100644 examples/ITK_Example23_OMEZarr.ipynb diff --git a/.binder/requirements.txt b/.binder/requirements.txt index f5d15858..cc22d0a0 100644 --- a/.binder/requirements.txt +++ b/.binder/requirements.txt @@ -4,6 +4,7 @@ jupyterlab>=2.2.0 imageio ipywidgets>=7.5.1 ipympl>=0.5.7 +ngff-zarr>=0.12.0 numpy torch>=2.0 monai>=1.2.0 diff --git a/.gitignore b/.gitignore index dac7be19..f7a43a4b 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ wasm/typescript/demo/ wasm/test micromamba/ .pixi/ +examples/result.ome.zarr/ diff --git a/examples/ITK_Example23_OMEZarr.ipynb b/examples/ITK_Example23_OMEZarr.ipynb new file mode 100644 index 00000000..d6bd8390 --- /dev/null +++ b/examples/ITK_Example23_OMEZarr.ipynb @@ -0,0 +1,561 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 23. OME-Zarr image registration" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### OME-Zarr" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[OME-Zarr](https://ngff.openmicroscopy.org/) is a cloud-optimized file format designed for storing and managing large-scale bioimaging data [1][2]. \n", + "\n", + "## Core Features\n", + "\n", + "**Storage Architecture**\n", + "- Stores N-dimensional typed arrays in individually accessible chunks\n", + "- Uses JSON for metadata storage and binary data in chunk-files\n", + "- Supports up to 5 dimensions in version 0.4 (time, channel, z, y, x)\n", + "\n", + "**Performance Optimization**\n", + "- Implements Google Maps-style multi-resolution pyramids for smooth zooming\n", + "- Offers configurable chunk compression using algorithms like GZIP or Blosc\n", + "- Enables efficient data access through colocated pixel storage\n", + "\n", + "**Data Organization**\n", + "- Uses hierarchical Zarr \"groups\" to organize multiple multi-dimensional pyramids\n", + "- Allows metadata attachment at each hierarchy level using JSON files\n", + "- Supports grouping of related data (raw images, deconvolutions, segmentations)\n", + "\n", + "## Spatial Metadata Support\n", + "\n", + "Version 0.4 introduced significant spatial metadata capabilities:\n", + "- Supports multi-dimensional raster images with associated volumetric data\n", + "- Enables spatial transformations for dataset alignment\n", + "\n", + "[1] https://www.biorxiv.org/content/10.1101/2023.02.17.528834v2.full\n", + "[2] https://pmc.ncbi.nlm.nih.gov/articles/PMC9980008/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ngff-zarr\n", + "\n", + "[ngff-zarr](https://ngff-zarr.readthedocs.io) is lean and kind OME-Zarr implementation.\n", + "\n", + "## ✨ Features\n", + "\n", + "- Minimal dependencies\n", + "- Work with arbitrary Zarr store types\n", + "- Lazy, parallel, and web ready -- no local filesystem required\n", + "- Process extremely large datasets\n", + "- Conversion of most bioimaging file formats\n", + "- Multiple downscaling methods\n", + "- Supports Python>=3.9\n", + "- Reads OME-Zarr v0.1 to v0.5 into simple Python data classes with Dask arrays\n", + "- Optional OME-Zarr data model validation during reading\n", + "- Writes OME-Zarr v0.4 to v0.5\n", + "- Optional writing via [tensorstore](https://google.github.io/tensorstore/)\n", + "\n", + "And interoperability with [ITK's Python bindings](https://docs.itk.org/en/latest/learn/python_quick_start.html) and [ITK-Wasm](https://wasm.itk.org) that work with [itk-elastix](https://pypi.org/project/itk-elastix/) and [itkwasm-elastix](https://pypi.org/project/itkwasm-elastix/)\n", + "\n", + "In this notebook, we'll register OME-Zarr images with `itk-elastix`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import itk\n", + "from itkwidgets import view\n", + "import ngff_zarr as nz\n", + "from rich import print\n", + "from zarr.storage import FSStore, LRUStoreCache\n", + "import zarr\n", + "import copy\n", + "import dask.array as da\n", + "import dask" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Multiscales(\n",
+       "    images=[\n",
+       "        NgffImage(\n",
+       "            data=dask.array<from-zarr, shape=(79, 201, 333, 333), dtype=uint16, chunksize=(1, 1, 333, 333), \n",
+       "chunktype=numpy.ndarray>,\n",
+       "            dims=['t', 'z', 'y', 'x'],\n",
+       "            scale={'t': 1.0, 'z': 1.0, 'y': 1.0, 'x': 1.0},\n",
+       "            translation={'t': 0.0, 'z': 0.0, 'y': 0.0, 'x': 0.0},\n",
+       "            name='image',\n",
+       "            axes_units={'t': None, 'z': None, 'y': None, 'x': None},\n",
+       "            computed_callbacks=[]\n",
+       "        ),\n",
+       "        NgffImage(\n",
+       "            data=dask.array<from-zarr, shape=(79, 201, 166, 166), dtype=uint16, chunksize=(1, 1, 166, 166), \n",
+       "chunktype=numpy.ndarray>,\n",
+       "            dims=['t', 'z', 'y', 'x'],\n",
+       "            scale={'t': 1.0, 'z': 1.0, 'y': 1.0, 'x': 1.0},\n",
+       "            translation={'t': 0.0, 'z': 0.0, 'y': 0.0, 'x': 0.0},\n",
+       "            name='image',\n",
+       "            axes_units={'t': None, 'z': None, 'y': None, 'x': None},\n",
+       "            computed_callbacks=[]\n",
+       "        ),\n",
+       "        NgffImage(\n",
+       "            data=dask.array<from-zarr, shape=(79, 201, 83, 83), dtype=uint16, chunksize=(1, 1, 83, 83), \n",
+       "chunktype=numpy.ndarray>,\n",
+       "            dims=['t', 'z', 'y', 'x'],\n",
+       "            scale={'t': 1.0, 'z': 1.0, 'y': 1.0, 'x': 1.0},\n",
+       "            translation={'t': 0.0, 'z': 0.0, 'y': 0.0, 'x': 0.0},\n",
+       "            name='image',\n",
+       "            axes_units={'t': None, 'z': None, 'y': None, 'x': None},\n",
+       "            computed_callbacks=[]\n",
+       "        )\n",
+       "    ],\n",
+       "    metadata=Metadata(\n",
+       "        axes=[\n",
+       "            Axis(name='t', type='time', unit=None),\n",
+       "            Axis(name='z', type='space', unit=None),\n",
+       "            Axis(name='y', type='space', unit=None),\n",
+       "            Axis(name='x', type='space', unit=None)\n",
+       "        ],\n",
+       "        datasets=[\n",
+       "            Dataset(path='0', coordinateTransformations=[]),\n",
+       "            Dataset(path='1', coordinateTransformations=[]),\n",
+       "            Dataset(path='2', coordinateTransformations=[])\n",
+       "        ],\n",
+       "        coordinateTransformations=None,\n",
+       "        omero=Omero(\n",
+       "            channels=[\n",
+       "                OmeroChannel(color='808080', window=OmeroWindow(min=0.0, max=65535.0, start=200.0, end=1500.0))\n",
+       "            ]\n",
+       "        ),\n",
+       "        name='image',\n",
+       "        version='0.3'\n",
+       "    ),\n",
+       "    scale_factors=None,\n",
+       "    method=None,\n",
+       "    chunks=None\n",
+       ")\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1;35mMultiscales\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mimages\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mNgffImage\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mdata\u001b[0m=\u001b[35mdask\u001b[0m.array\u001b[1m<\u001b[0m\u001b[1;95mfrom-zarr\u001b[0m\u001b[39m, \u001b[0m\u001b[33mshape\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m79\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m201\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m, \u001b[0m\u001b[33mdtype\u001b[0m\u001b[39m=\u001b[0m\u001b[35muint16\u001b[0m\u001b[39m, \u001b[0m\u001b[33mchunksize\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m, \u001b[0m\n", + "\u001b[33mchunktype\u001b[0m\u001b[39m=\u001b[0m\u001b[35mnumpy\u001b[0m\u001b[39m.ndarray>,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mdims\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m[\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[1;39m]\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mscale\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m{\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[1;39m}\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mtranslation\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m{\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[1;39m}\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mname\u001b[0m\u001b[39m=\u001b[0m\u001b[32m'image'\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33maxes_units\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m{\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[1;39m}\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mcomputed_callbacks\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m[\u001b[0m\u001b[1;39m]\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[1;35mNgffImage\u001b[0m\u001b[1;39m(\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mdata\u001b[0m\u001b[39m=\u001b[0m\u001b[35mdask\u001b[0m\u001b[39m.array,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mdims\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m[\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[1;39m]\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mscale\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m{\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m1.0\u001b[0m\u001b[1;39m}\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mtranslation\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m{\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[39m: \u001b[0m\u001b[1;36m0.0\u001b[0m\u001b[1;39m}\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mname\u001b[0m\u001b[39m=\u001b[0m\u001b[32m'image'\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33maxes_units\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m{\u001b[0m\u001b[32m't'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'z'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'y'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[39m, \u001b[0m\u001b[32m'x'\u001b[0m\u001b[39m: \u001b[0m\u001b[3;35mNone\u001b[0m\u001b[1;39m}\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mcomputed_callbacks\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m[\u001b[0m\u001b[1;39m]\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m,\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[1;35mNgffImage\u001b[0m\u001b[1;39m(\u001b[0m\n", + "\u001b[39m \u001b[0m\u001b[33mdata\u001b[0m\u001b[39m=\u001b[0m\u001b[35mdask\u001b[0m\u001b[39m.array\u001b[0m,\n", + " \u001b[33mdims\u001b[0m=\u001b[1m[\u001b[0m\u001b[32m't'\u001b[0m, \u001b[32m'z'\u001b[0m, \u001b[32m'y'\u001b[0m, \u001b[32m'x'\u001b[0m\u001b[1m]\u001b[0m,\n", + " \u001b[33mscale\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m't'\u001b[0m: \u001b[1;36m1.0\u001b[0m, \u001b[32m'z'\u001b[0m: \u001b[1;36m1.0\u001b[0m, \u001b[32m'y'\u001b[0m: \u001b[1;36m1.0\u001b[0m, \u001b[32m'x'\u001b[0m: \u001b[1;36m1.0\u001b[0m\u001b[1m}\u001b[0m,\n", + " \u001b[33mtranslation\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m't'\u001b[0m: \u001b[1;36m0.0\u001b[0m, \u001b[32m'z'\u001b[0m: \u001b[1;36m0.0\u001b[0m, \u001b[32m'y'\u001b[0m: \u001b[1;36m0.0\u001b[0m, \u001b[32m'x'\u001b[0m: \u001b[1;36m0.0\u001b[0m\u001b[1m}\u001b[0m,\n", + " \u001b[33mname\u001b[0m=\u001b[32m'image'\u001b[0m,\n", + " \u001b[33maxes_units\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m't'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'z'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'y'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'x'\u001b[0m: \u001b[3;35mNone\u001b[0m\u001b[1m}\u001b[0m,\n", + " \u001b[33mcomputed_callbacks\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m\n", + " \u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[33mmetadata\u001b[0m=\u001b[1;35mMetadata\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33maxes\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mAxis\u001b[0m\u001b[1m(\u001b[0m\u001b[33mname\u001b[0m=\u001b[32m't'\u001b[0m, \u001b[33mtype\u001b[0m=\u001b[32m'time'\u001b[0m, \u001b[33munit\u001b[0m=\u001b[3;35mNone\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[1;35mAxis\u001b[0m\u001b[1m(\u001b[0m\u001b[33mname\u001b[0m=\u001b[32m'z'\u001b[0m, \u001b[33mtype\u001b[0m=\u001b[32m'space'\u001b[0m, \u001b[33munit\u001b[0m=\u001b[3;35mNone\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[1;35mAxis\u001b[0m\u001b[1m(\u001b[0m\u001b[33mname\u001b[0m=\u001b[32m'y'\u001b[0m, \u001b[33mtype\u001b[0m=\u001b[32m'space'\u001b[0m, \u001b[33munit\u001b[0m=\u001b[3;35mNone\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[1;35mAxis\u001b[0m\u001b[1m(\u001b[0m\u001b[33mname\u001b[0m=\u001b[32m'x'\u001b[0m, \u001b[33mtype\u001b[0m=\u001b[32m'space'\u001b[0m, \u001b[33munit\u001b[0m=\u001b[3;35mNone\u001b[0m\u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[33mdatasets\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mDataset\u001b[0m\u001b[1m(\u001b[0m\u001b[33mpath\u001b[0m=\u001b[32m'0'\u001b[0m, \u001b[33mcoordinateTransformations\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[1;35mDataset\u001b[0m\u001b[1m(\u001b[0m\u001b[33mpath\u001b[0m=\u001b[32m'1'\u001b[0m, \u001b[33mcoordinateTransformations\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m\u001b[1m)\u001b[0m,\n", + " \u001b[1;35mDataset\u001b[0m\u001b[1m(\u001b[0m\u001b[33mpath\u001b[0m=\u001b[32m'2'\u001b[0m, \u001b[33mcoordinateTransformations\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m\u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m,\n", + " \u001b[33mcoordinateTransformations\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33momero\u001b[0m=\u001b[1;35mOmero\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mchannels\u001b[0m=\u001b[1m[\u001b[0m\n", + " \u001b[1;35mOmeroChannel\u001b[0m\u001b[1m(\u001b[0m\u001b[33mcolor\u001b[0m=\u001b[32m'808080'\u001b[0m, \u001b[33mwindow\u001b[0m=\u001b[1;35mOmeroWindow\u001b[0m\u001b[1m(\u001b[0m\u001b[33mmin\u001b[0m=\u001b[1;36m0\u001b[0m\u001b[1;36m.0\u001b[0m, \u001b[33mmax\u001b[0m=\u001b[1;36m65535\u001b[0m\u001b[1;36m.0\u001b[0m, \u001b[33mstart\u001b[0m=\u001b[1;36m200\u001b[0m\u001b[1;36m.0\u001b[0m, \u001b[33mend\u001b[0m=\u001b[1;36m1500\u001b[0m\u001b[1;36m.0\u001b[0m\u001b[1m)\u001b[0m\u001b[1m)\u001b[0m\n", + " \u001b[1m]\u001b[0m\n", + " \u001b[1m)\u001b[0m,\n", + " \u001b[33mname\u001b[0m=\u001b[32m'image'\u001b[0m,\n", + " \u001b[33mversion\u001b[0m=\u001b[32m'0.3'\u001b[0m\n", + " \u001b[1m)\u001b[0m,\n", + " \u001b[33mscale_factors\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mmethod\u001b[0m=\u001b[3;35mNone\u001b[0m,\n", + " \u001b[33mchunks\u001b[0m=\u001b[3;35mNone\u001b[0m\n", + "\u001b[1m)\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# From the IDR OME-NGFF Samples\n", + "image_url = 'https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0051A/4007817.zarr'\n", + "\n", + "fs_store = FSStore(image_url)\n", + "# Least recently used cache -- avoid re-fetching timepoints\n", + "lru_store = LRUStoreCache(fs_store, max_size=1e9)\n", + "ome_zarr = nz.from_ngff_zarr(lru_store, version='0.3')\n", + "\n", + "# 3D time series\n", + "print(ome_zarr)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
NgffImage(\n",
+       "    data=dask.array<from-zarr, shape=(79, 201, 333, 333), dtype=uint16, chunksize=(1, 1, 333, 333), \n",
+       "chunktype=numpy.ndarray>,\n",
+       "    dims=['t', 'z', 'y', 'x'],\n",
+       "    scale={'t': 1.0, 'z': 1.0, 'y': 1.0, 'x': 1.0},\n",
+       "    translation={'t': 0.0, 'z': 0.0, 'y': 0.0, 'x': 0.0},\n",
+       "    name='image',\n",
+       "    axes_units={'t': None, 'z': None, 'y': None, 'x': None},\n",
+       "    computed_callbacks=[]\n",
+       ")\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1;35mNgffImage\u001b[0m\u001b[1m(\u001b[0m\n", + " \u001b[33mdata\u001b[0m=\u001b[35mdask\u001b[0m.array\u001b[1m<\u001b[0m\u001b[1;95mfrom-zarr\u001b[0m\u001b[39m, \u001b[0m\u001b[33mshape\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m79\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m201\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m, \u001b[0m\u001b[33mdtype\u001b[0m\u001b[39m=\u001b[0m\u001b[35muint16\u001b[0m\u001b[39m, \u001b[0m\u001b[33mchunksize\u001b[0m\u001b[39m=\u001b[0m\u001b[1;39m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m1\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[39m, \u001b[0m\u001b[1;36m333\u001b[0m\u001b[1;39m)\u001b[0m\u001b[39m, \u001b[0m\n", + "\u001b[33mchunktype\u001b[0m\u001b[39m=\u001b[0m\u001b[35mnumpy\u001b[0m\u001b[39m.ndarray\u001b[0m\u001b[1m>\u001b[0m,\n", + " \u001b[33mdims\u001b[0m=\u001b[1m[\u001b[0m\u001b[32m't'\u001b[0m, \u001b[32m'z'\u001b[0m, \u001b[32m'y'\u001b[0m, \u001b[32m'x'\u001b[0m\u001b[1m]\u001b[0m,\n", + " \u001b[33mscale\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m't'\u001b[0m: \u001b[1;36m1.0\u001b[0m, \u001b[32m'z'\u001b[0m: \u001b[1;36m1.0\u001b[0m, \u001b[32m'y'\u001b[0m: \u001b[1;36m1.0\u001b[0m, \u001b[32m'x'\u001b[0m: \u001b[1;36m1.0\u001b[0m\u001b[1m}\u001b[0m,\n", + " \u001b[33mtranslation\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m't'\u001b[0m: \u001b[1;36m0.0\u001b[0m, \u001b[32m'z'\u001b[0m: \u001b[1;36m0.0\u001b[0m, \u001b[32m'y'\u001b[0m: \u001b[1;36m0.0\u001b[0m, \u001b[32m'x'\u001b[0m: \u001b[1;36m0.0\u001b[0m\u001b[1m}\u001b[0m,\n", + " \u001b[33mname\u001b[0m=\u001b[32m'image'\u001b[0m,\n", + " \u001b[33maxes_units\u001b[0m=\u001b[1m{\u001b[0m\u001b[32m't'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'z'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'y'\u001b[0m: \u001b[3;35mNone\u001b[0m, \u001b[32m'x'\u001b[0m: \u001b[3;35mNone\u001b[0m\u001b[1m}\u001b[0m,\n", + " \u001b[33mcomputed_callbacks\u001b[0m=\u001b[1m[\u001b[0m\u001b[1m]\u001b[0m\n", + "\u001b[1m)\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Working with the first scale\n", + "ngff_image = ome_zarr.images[0]\n", + "\n", + "# For visualization\n", + "vmin = ome_zarr.metadata.omero.channels[0].window.start\n", + "vmax = ome_zarr.metadata.omero.channels[0].window.end\n", + "\n", + "print(ngff_image)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "window.connectPlugin && window.connectPlugin(\"3d45be0d-b316-48ac-adc8-1e3f23f98a4e\")" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "fixed_image = nz.ngff_image_to_itk_image(ngff_image, wasm=False, t_index=0)\n", + "view(fixed_image, vmin=vmin, vmax=vmax)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "window.connectPlugin && window.connectPlugin(\"3d45be0d-b316-48ac-adc8-1e3f23f98a4e\")" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "moving_image = nz.ngff_image_to_itk_image(ngff_image, wasm=False, t_index=50)\n", + "view(moving_image, vmin=vmin, vmax=vmax)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The function calls in the 3D case to import and register the images is similar to the 2D case. Masks, usually binary images, are import with the itk library similar to the images. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Registration" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Any of the registration interfaces described in the other notebooks in the repository can be used." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "window.connectPlugin && window.connectPlugin(\"3d45be0d-b316-48ac-adc8-1e3f23f98a4e\")" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "parameter_object = itk.ParameterObject.New()\n", + "resolutions = 3\n", + "parameter_map_rigid = parameter_object.GetDefaultParameterMap('rigid', resolutions)\n", + "parameter_object.AddParameterMap(parameter_map_rigid)\n", + "\n", + "result_image, result_transform_parameters = itk.elastix_registration_method(\n", + " fixed_image, moving_image,\n", + " parameter_object=parameter_object)\n", + "\n", + "view(result_image)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Write the result to disk as an OME-Zarr." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "result_ngff = nz.itk_image_to_ngff_image(result_image)\n", + "result_ngff.axes_units = ome_zarr.metadata.axes[0].unit\n", + "\n", + "result_multiscales = nz.to_multiscales(result_image)\n", + "result_multiscales.metadata.omero = ome_zarr.metadata.omero\n", + "\n", + "nz.to_ngff_zarr('result.ome.zarr', result_multiscales)" + ] + } + ], + "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.11.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}