diff --git a/.binder/requirements.txt b/.binder/requirements.txt index 2b31e4b7..cc22d0a0 100644 --- a/.binder/requirements.txt +++ b/.binder/requirements.txt @@ -4,12 +4,11 @@ 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 matplotlib==3.3.1 -PyQt5==5.15.0 -PyQt5-sip==12.8.0 -QtPy==1.9.0 +PySide2 voila tqdm 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 +}