{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [], "source": [ "########################################################################\n", "# File : using_apeer-ometiff-library.ipynb\n", "# Version : 0.2\n", "# Author : czsrh\n", "# Date : 13.01.2019\n", "# Institution : Carl Zeiss Microscopy GmbH\n", "#\n", "# Disclaimer: Just for testing - Use at your own risk.\n", "# Feedback or Improvements are welcome.\n", "########################################################################" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "***Reading OME-TIFF files from Python using the apeer-ometiff-library***\n", "\n", "The APEER platform allows creating modules and workflows using basically any programming language due to its underlying Docker(TM) technology.\n", "Nevertheless Python seems to be the favorite choice for most of the time for various reasons:\n", "\n", "* Simple enough to be used by researchers with scripting experience\n", "* Powerful enough to create amazing computational tools\n", "* A huge and very open community and the whole ecosystem behind it\n", "* Probably the most popular language when it come to topics like Machine Learning\n", "\n", "The topic or question what is the \"best\" image data format for microscopy is a very interesting and also quite difficult\n", "question. There are no easy answers and there is no right or wrong here.\n", "\n", "Since the APEER platform tries to provide solutions our team decided that we must for sure support the currently most popular\n", "image data format for microscoscopy image data, which clearly is OME-TIFF (despite its known limitations).\n", "We explored \"easy and simple\" ways to read OME-TIFF for the most common use cases. We just want a simple python-based tool to read and write OME-TIFF without the need to include JAVA etc. into the modules.\n", "Therefore we reused parts of the existing python ecossystem, especially python-bioformats and tifffile, added some extra code and created a basic PyPi package.\n", "\n", "This package can be easily inclued in every APEER module but obviousy it can be also used inside our python application or within jupyter notebook.\n", "\n", "* [PyPi - apeer-ometiff-library](https://pypi.org/project/apeer-ometiff-library/)\n", "\n", "* [PyPi - python-bioformats](https://pypi.org/project/python-bioformats/).\n", "\n", "More information on the source code can be found on the APEER GitHub project page: [GitHub - apeer-ometiff-library](https://github.com/apeer-micro/apeer-ometiff-library)\n", " \n", "In order to make things a bit easier we create a little helper script called imgfileutils.py which can be found here\n", "\n", "* [ZEISS GitHub OAD - imagefileutils.py](https://github.com/zeiss-microscopy/OAD/blob/master/jupyter_notebooks/Read_CZI_and_OMETIFF_and_display_widgets_and_napari/modules/imgfileutils.py)\n", "\n", "The complete notebook can be found here:\n", " \n", "* [ZEISS GitHub OAD - using_apeer-ometiff-library.ipynb](https://github.com/zeiss-microscopy/OAD/blob/master/jupyter_notebooks/Read_CZI_and_OMETIFF_and_display_widgets_and_napari/using_apeer-ometiff-library.ipynb)\n", "\n", "Remark: The notebook uses a small subset of the original dataset because of the file size. Therefore the images used\n", "for illustration do not exactly correspond to what one will see if using the provided test files." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [], "source": [ "# import the libraries\n", "from apeer_ometiff_library import io, processing, omexmlClass\n", "\n", "# import script with some useful functions\n", "import sys\n", "sys.path.append(r'modules')\n", "import imgfileutils as imf" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created OME-XML file for testdata: testdata\\CellDivision_T=10_Z=15_CH=2_DCV_small.ome.tiff\n" ] } ], "source": [ "# define your OME-TIFF file here\n", "filename = r'testdata\\CellDivision_T=10_Z=15_CH=2_DCV_small.ome.tiff'\n", "\n", "# extract XML and save it to disk\n", "xmlometiff = imf.writexml_ometiff(filename)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "### Reading the OME-TIFF stack as an NumPy Array\n", "\n", "The easily ready and OME-TIFF stack without the need to deal with the JAVA runtime the apeer-ometiff-library used the following code:\n", " \n", "```python\n", "def read_ometiff(input_path):\n", " with tifffile.TiffFile(input_path) as tif:\n", " array = tif.asarray()\n", " omexml_string = tif[0].image_description.decode('utf-8')\n", "\n", " # Turn Ome XML String to an Bioformats object for parsing\n", " metadata = omexmlClass.OMEXML(omexml_string)\n", "\n", " # Parse pixel sizes\n", " pixels = metadata.image(0).Pixels\n", " size_c = pixels.SizeC\n", " size_t = pixels.SizeT\n", " size_z = pixels.SizeZ\n", " size_x = pixels.SizeX\n", " size_y = pixels.SizeY\n", "\n", " # Expand image array to 5D of order (T, Z, C, X, Y)\n", " if size_c == 1:\n", " array = np.expand_dims(array, axis=-3)\n", " if size_z == 1:\n", " array = np.expand_dims(array, axis=-4)\n", " if size_t == 1:\n", " array = np.expand_dims(array, axis=-5)\n", "\n", " return array, omexml_string\n", "```" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Image Type: ometiff\n" ] } ], "source": [ "# Read metadata and array differently for OME-TIFF by using the io function of the apeer-ometiff library\n", " \n", "# Return value is an array of order (T, Z, C, X, Y)\n", "array, omexml = io.read_ometiff(filename)\n", "\n", "# get the metadata for the OME-TIFF file\n", "metadata, add_metadata = imf.get_metadata(filename)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Array Shape: (10, 15, 2, 256, 256)\n", "Dimension Order (BioFormats) : TZCYX\n", "SizeT : 10\n", "SizeZ : 15\n", "SizeC : 2\n", "SizeX : 256\n", "SizeY : 256\n", "XScale: 0.09057667415221031\n", "YScale: 0.09057667415221031\n", "ZScale: 0.32\n" ] } ], "source": [ "# check the shape of numpy array containing the pixel data\n", "print('Array Shape: ', array.shape)\n", "\n", "# get dimension order from metadata\n", "print('Dimension Order (BioFormats) : ', metadata['DimOrder BF Array'])\n", "\n", "# show dimensions and scaling\n", "print('SizeT : ', metadata['SizeT'])\n", "print('SizeZ : ', metadata['SizeZ'])\n", "print('SizeC : ', metadata['SizeC'])\n", "print('SizeX : ', metadata['SizeX'])\n", "print('SizeY : ', metadata['SizeY'])\n", "print('XScale: ', metadata['XScale'])\n", "print('YScale: ', metadata['YScale'])\n", "print('ZScale: ', metadata['ZScale'])" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Directory : testdata\n", "Filename : CellDivision_T=10_Z=15_CH=2_DCV_small.ome.tiff\n", "Extension : ome.tiff\n", "ImageType : ometiff\n", "Name : CellDivision_T=10_Z=15_CH=2_DCV_small.czi #1\n", "AcqDate : 2016-02-12T09:41:02.491\n", "TotalSeries : 1\n", "SizeX : 256\n", "SizeY : 256\n", "SizeZ : 15\n", "SizeC : 2\n", "SizeT : 10\n", "Sizes BF : [1, 10, 15, 2, 256, 256]\n", "DimOrder BF : XYCZT\n", "DimOrder BF Array : TZCYX\n", "DimOrder CZI : None\n", "Axes : None\n", "Shape : None\n", "isRGB : None\n", "ObjNA : 1.2\n", "ObjMag : 50.0\n", "ObjID : Objective:1\n", "ObjName : None\n", "ObjImmersion : None\n", "XScale : 0.09057667415221031\n", "YScale : 0.09057667415221031\n", "ZScale : 0.32\n", "XScaleUnit : µm\n", "YScaleUnit : µm\n", "ZScaleUnit : µm\n", "DetectorModel : None\n", "DetectorName : []\n", "DetectorID : Detector:506\n", "InstrumentID : Instrument:0\n", "Channels : ['LED555', 'LED470']\n", "ImageIDs : [0]\n", "NumPy.dtype : None\n" ] } ], "source": [ "# show the complete metadata dictionary\n", "for key, value in metadata.items():\n", " # print all key-value pairs for the dictionary\n", " print(key, ' : ', value)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "f234be48aaac46a8ac89e33480c06ba0", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Output()" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "4a9fe6ff9d1e4d98b2898071e618e706", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(IntSlider(value=1, continuous_update=False, description='Time:', max=10, min=1), IntSlider(valu…" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Here we use https://ipywidgets.readthedocs.io/en/latest/ to create some simple and interactive\n", "# controls to navigate through the planes of an multi-dimensional NumPy Array. \n", "\n", "# display data using ipywidgets\n", "ui, out = imf.create_ipyviewer_ome_tiff(array, metadata)\n", "\n", "# show the interactive widget\n", "display(ui, out)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "![IpyWidget Viewer](images/display_ometiff_ipywidgets.png \"IpyWidget Viewer\")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "slide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Initializing Napari Viewer ...\n", "Dim PosT : 0\n", "Dim PosC : 2\n", "Dim PosZ : 1\n", "Scale Factors : [1.0, 3.533, 1.0, 1.0, 1.0]\n", "Shape Channel : 0 (10, 15, 256, 256)\n", "Scaling Factors: [1.0, 3.533, 1.0, 1.0, 1.0]\n", "Scaling: [0, 4927.0]\n", "Shape Channel : 1 (10, 15, 256, 256)\n", "Scaling Factors: [1.0, 3.533, 1.0, 1.0, 1.0]\n", "Scaling: [0, 25331.0]\n" ] } ], "source": [ "# Here we use the Napari viewer (https://github.com/napari/napari) to visualize the\n", "# complete OME-TIFF stack, which is represented by a multi-dimensional NumPy Array. \n", "\n", "# configure napari automatically based on metadata and show the OME-TIFF stack\n", "imf.show_napari(array, metadata)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "![Napari Viewer](images/display_ometiff_napari.png \"Napari Viewer\")" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "In order to create a slideshow using this notebook run the following lines from a command line:\n", "\n", "```bash\n", "cd c:\\Users\\...\\jupyter_notebooks\\Read_CZI_and_OMETIFF_and_display_widgets_and_napari\n", "\n", "jupyter nbconvert using_apeer-ometiff-library.ipynb --to slides --post serve\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Slideshow", "file_extension": ".py", "kernelspec": { "display_name": "Python 3", "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.7.4" }, "mimetype": "text/x-python", "name": "python", "npconvert_exporter": "python", "pygments_lexer": "ipython3", "version": 3 }, "nbformat": 4, "nbformat_minor": 2 }