{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Simple FRAP script" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This script analyzes a fluorescence time-lapse image, measuring the intensity in a named Channel within a ROI. The intensity is plotted over time." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Install dependencies if required\n", "The cell below will install dependencies if you choose to run the notebook in [Google Colab](https://colab.research.google.com/notebooks/intro.ipynb#recent=true). " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: omero-py in /srv/conda/envs/notebook/lib/python3.7/site-packages (5.9.0)\n", "Requirement already satisfied: zeroc-ice<3.7,>=3.6.4 in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (3.6.5)\n", "Requirement already satisfied: PyYAML in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (5.4.1)\n", "Requirement already satisfied: future in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (0.18.2)\n", "Requirement already satisfied: numpy in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (1.19.4)\n", "Requirement already satisfied: Pillow in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (8.1.2)\n", "Requirement already satisfied: appdirs in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (1.4.4)\n", "Requirement already satisfied: requests in /srv/conda/envs/notebook/lib/python3.7/site-packages (from omero-py) (2.24.0)\n", "Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /srv/conda/envs/notebook/lib/python3.7/site-packages (from requests->omero-py) (1.25.10)\n", "Requirement already satisfied: chardet<4,>=3.0.2 in /srv/conda/envs/notebook/lib/python3.7/site-packages (from requests->omero-py) (3.0.4)\n", "Requirement already satisfied: idna<3,>=2.5 in /srv/conda/envs/notebook/lib/python3.7/site-packages (from requests->omero-py) (2.10)\n", "Requirement already satisfied: certifi>=2017.4.17 in /srv/conda/envs/notebook/lib/python3.7/site-packages (from requests->omero-py) (2020.6.20)\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "%pip install omero-py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Import packages" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "from omero.gateway import BlitzGateway, MapAnnotationWrapper\n", "from omero.model import EllipseI\n", "from PIL import Image\n", "import numpy as np\n", "import matplotlib\n", "from matplotlib import pyplot as plt\n", "from getpass import getpass\n", "# only used in the Jupyter notebook context for displaying a plot:\n", "from IPython.display import Image as ipImage, display\n", "import ipywidgets as widgets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Create a connection to the OMERO Server\n", "\n", "You will be asked to enter username and password when running the next cell. Please press Enter after each. " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Username: trainer-1\n", "OMERO Password: ········\n", "Connected as trainer-1\n" ] } ], "source": [ "def connect(hostname, username, password):\n", " \"\"\"\n", " Connect to an OMERO server\n", " :param hostname: Host name\n", " :param username: User\n", " :param password: Password\n", " :return: Connected BlitzGateway\n", " \"\"\"\n", " conn = BlitzGateway(username, password,\n", " host=hostname, secure=True)\n", " conn.connect()\n", " conn.c.enableKeepAlive(60)\n", " return conn\n", "\n", "HOST = 'wss://workshop.openmicroscopy.org/omero-ws'\n", "conn = connect(HOST, input(\"Username: \"), getpass(\"OMERO Password: \"))\n", "print(\"Connected as {}\".format(conn.getUser().getName()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load Image" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Image ID: 28662\n", "Image U20S-RCC1.10_R3D_FRAP.dv loaded\n" ] } ], "source": [ "image_id = input(\"Image ID: \")\n", "img = conn.getObject(\"Image\", image_id)\n", "print(\"Image {} loaded\".format(img.getName()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Select the relevant channel" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "6c50e90738c04b3ebf981c1ee056f7ff", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Dropdown(description='Name: ', options=('528.0', '1', '2'), value='528.0')" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def dropdown_widget(values,\n", " dropdown_widget_name,\n", " displaywidget=False):\n", "\n", " alg_sel = widgets.Dropdown(\n", " options=values,\n", " value=values[0],\n", " description=dropdown_widget_name,\n", " disabled=False,\n", " )\n", " if displaywidget is True:\n", " display(alg_sel)\n", " return alg_sel\n", "\n", "labels = img.getChannelLabels()\n", "channel_name = dropdown_widget(\n", " img.getChannelLabels(),\n", " 'Name: ', True\n", ")" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Channel index: 0\n" ] } ], "source": [ "channel_idx = labels.index(channel_name.value)\n", "print(\"Channel index: {}\".format(channel_idx))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get the ellipse ROI:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_ellipse_roi(conn, image):\n", " \"\"\"\n", " Get the first ellipse ROI found in the image\n", " :param conn: The BlitzGateway\n", " :param image: The Image\n", " :return: The shape ID of the first ellipse ROI found\n", " \"\"\"\n", " roi_service = conn.getRoiService()\n", " result = roi_service.findByImage(image.getId(), None)\n", " shape_id = None\n", " for roi in result.rois:\n", " for s in roi.copyShapes():\n", " if type(s) == EllipseI:\n", " shape_id = s.id.val\n", " return shape_id\n", "\n", "ellipse_id = get_ellipse_roi(conn, img)\n", "print(\"Shape ID: {}\".format(ellipse_id))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get the mean intensities" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_mean_intensities(conn, image, the_c, shape_id):\n", " \"\"\"\n", " Get the mean pixel intensities of a ROI in a time series image\n", " :param conn: The BlitzGateway\n", " :param image: The image\n", " :param the_c: The channel index\n", " :param shape_id: The ROI shape id\n", " :return: List of mean intensity values (one for each timepoint)\n", " \"\"\"\n", " roi_service = conn.getRoiService()\n", " the_z = 0\n", " size_t = image.getSizeT()\n", " meanvalues = []\n", " for t in range(size_t):\n", " stats = roi_service.getShapeStatsRestricted([shape_id],\n", " the_z, t, [the_c])\n", " meanvalues.append(stats[0].mean[0])\n", " return meanvalues\n", "\n", "values = get_mean_intensities(conn, img, channel_idx, ellipse_id)\n", "print(values)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot the data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def plot(values, plot_filename):\n", " \"\"\"\n", " Create a simple plot of the given values\n", " and saves it.\n", " :param values: The values\n", " :param plot_filename: The file name\n", " :return: Nothing\n", " \"\"\"\n", " matplotlib.use('Agg')\n", " fig = plt.figure()\n", " plt.subplot(111)\n", " plt.plot(values)\n", " fig.canvas.draw()\n", " fig.savefig(plot_filename)\n", " pil_img = Image.open(plot_filename)\n", " pil_img.show()\n", "\n", "plot(values, \"plot.png\")\n", "display(ipImage(\"plot.png\"))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Save the results" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def save_values(conn, image, values):\n", " \"\"\"\n", " Attach the values as map annotation to the image\n", " :param conn: The BlitzGateway\n", " :param image: The image\n", " :param values: The values\n", " :return: Nothing\n", " \"\"\"\n", " namespace = \"demo.simple_frap_data\"\n", " key_value_data = [[str(t), str(value)] for t, value in enumerate(values)]\n", " map_ann = MapAnnotationWrapper(conn)\n", " map_ann.setNs(namespace)\n", " map_ann.setValue(key_value_data)\n", " map_ann.save()\n", " image.linkAnnotation(map_ann)\n", " \n", "save_values(conn, img, values)\n", "print(\"Values saved.\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def save_plot(conn, image, plot_filename):\n", " \"\"\"\n", " Save the plot to OMERO\n", " :param conn: The BlitzGateway\n", " :param image: The image\n", " :param plot_filename: The path to the plot image\n", " :return: Nothing\n", " \"\"\"\n", " pil_img = Image.open(plot_filename)\n", " np_array = np.asarray(pil_img)\n", " red = np_array[::, ::, 0]\n", " green = np_array[::, ::, 1]\n", " blue = np_array[::, ::, 2]\n", " plane_gen = iter([red, green, blue])\n", " conn.createImageFromNumpySeq(plane_gen, plot_filename, sizeC=3,\n", " dataset=image.getParent())\n", " \n", "save_plot(conn, img, \"plot.png\")\n", "print(\"Plot saved.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Close the connection" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def disconnect(conn):\n", " \"\"\"\n", " Disconnect from an OMERO server\n", " :param conn: The BlitzGateway\n", " \"\"\"\n", " conn.close()\n", "\n", "disconnect(conn)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### License (BSD 2-Clause)\n", "Copyright (C) 2019-2020 University of Dundee. All Rights Reserved.\n", "\n", "Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n", "\n", "Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n", "Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n", "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ] } ], "metadata": { "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.8" } }, "nbformat": 4, "nbformat_minor": 4 }