{ "cells": [ { "cell_type": "markdown", "id": "c986fd14-4622-47fc-83c3-e52154693dd9", "metadata": {}, "source": [ "# Wiggle nuclei\n", "In this notebook we move the positions of nuclei artifically to afterwards segment them again and draw a mesh between them. The mesh will change more or less depending on how much we modify the nuclei positions randomly." ] }, { "cell_type": "code", "execution_count": 1, "id": "c088c2d9-5229-4148-899a-8ff4ec33a51c", "metadata": {}, "outputs": [], "source": [ "# !pip install napari-animated-gif-io pyclesperanto-prototype stackview" ] }, { "cell_type": "code", "execution_count": 2, "id": "5977262a-cf94-48de-94e1-21d24e465ed4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "import pyclesperanto_prototype as cle\n", "from napari_animated_gif_io._function import save_as_animated_gif\n", "\n", "cle.select_device(\"tx\")\n" ] }, { "cell_type": "markdown", "id": "dd3287ea-a355-4608-8306-a3d0171dccb8", "metadata": {}, "source": [ "## Load data\n", "Tribolium castaneum, nuclei-GFP transgenic line, cropped. Image data source: Daniela Vorkel, Myers lab, MPI-CBG / CSBD\n", " \n", "https://github.com/clEsperanto/clesperanto_example_data/blob/main/Lund_000500_resampled-cropped.tif" ] }, { "cell_type": "code", "execution_count": 3, "id": "97c601d8-7435-4698-b461-2a194cd64517", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "cle._ image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(100, 256, 256)
dtypefloat32
size25.0 MB
min125.0
max680.0
\n", "\n", "
" ], "text/plain": [ "cl.OCLArray([[[144., 142., 145., ..., 140., 138., 137.],\n", " [145., 142., 143., ..., 141., 139., 138.],\n", " [142., 139., 141., ..., 140., 139., 142.],\n", " ...,\n", " [256., 252., 260., ..., 308., 287., 273.],\n", " [253., 249., 253., ..., 319., 298., 278.],\n", " [256., 255., 253., ..., 322., 296., 273.]],\n", "\n", " [[143., 140., 145., ..., 139., 139., 137.],\n", " [145., 139., 144., ..., 140., 140., 138.],\n", " [143., 140., 142., ..., 141., 140., 141.],\n", " ...,\n", " [255., 255., 263., ..., 314., 292., 274.],\n", " [255., 250., 251., ..., 328., 302., 277.],\n", " [257., 253., 250., ..., 329., 298., 272.]],\n", "\n", " [[143., 139., 145., ..., 139., 139., 137.],\n", " [145., 138., 145., ..., 139., 141., 137.],\n", " [143., 140., 142., ..., 142., 141., 141.],\n", " ...,\n", " [254., 257., 265., ..., 316., 293., 272.],\n", " [255., 251., 250., ..., 330., 302., 274.],\n", " [257., 251., 248., ..., 332., 298., 270.]],\n", "\n", " ...,\n", "\n", " [[137., 138., 140., ..., 128., 127., 129.],\n", " [140., 140., 137., ..., 131., 127., 129.],\n", " [140., 138., 138., ..., 129., 130., 133.],\n", " ...,\n", " [177., 182., 181., ..., 160., 161., 161.],\n", " [179., 185., 186., ..., 162., 157., 158.],\n", " [181., 179., 184., ..., 158., 157., 160.]],\n", "\n", " [[136., 138., 141., ..., 127., 127., 129.],\n", " [139., 139., 136., ..., 131., 127., 129.],\n", " [140., 137., 138., ..., 127., 128., 134.],\n", " ...,\n", " [175., 179., 179., ..., 158., 159., 159.],\n", " [177., 182., 184., ..., 162., 155., 158.],\n", " [180., 174., 180., ..., 158., 157., 158.]],\n", "\n", " [[136., 136., 139., ..., 129., 129., 129.],\n", " [137., 137., 135., ..., 130., 128., 128.],\n", " [138., 135., 136., ..., 128., 130., 132.],\n", " ...,\n", " [174., 176., 177., ..., 159., 157., 157.],\n", " [179., 180., 180., ..., 160., 154., 156.],\n", " [178., 174., 177., ..., 158., 156., 157.]]], dtype=float32)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image = cle.imread(\"../../../clesperanto_example_data/Lund_000500_resampled-cropped.tif\")\n", "image" ] }, { "cell_type": "markdown", "id": "d99dd600-a055-4431-8923-e07c87db5839", "metadata": {}, "source": [ "## Segment nuclei" ] }, { "cell_type": "code", "execution_count": 4, "id": "efe5810d-fe37-4e97-939d-72161d818864", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "
\n", "\n", "\n", "cle._ image
\n", "\n", "\n", "\n", "\n", "\n", "
shape(100, 256, 256)
dtypeuint32
size25.0 MB
min0.0
max285.0
\n", "\n", "
" ], "text/plain": [ "cl.OCLArray([[[ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [ 0, 0, 0, ..., 285, 285, 0],\n", " [ 0, 0, 0, ..., 285, 285, 0],\n", " [ 0, 0, 0, ..., 285, 285, 0]],\n", "\n", " [[ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [ 0, 0, 0, ..., 285, 285, 0],\n", " [ 0, 0, 0, ..., 285, 285, 0],\n", " [ 0, 0, 0, ..., 285, 285, 0]],\n", "\n", " [[ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [ 0, 0, 0, ..., 285, 0, 0],\n", " [ 0, 0, 0, ..., 285, 285, 0],\n", " [ 0, 0, 0, ..., 285, 285, 0]],\n", "\n", " ...,\n", "\n", " [[ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0]],\n", "\n", " [[ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0]],\n", "\n", " [[ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " ...,\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0],\n", " [ 0, 0, 0, ..., 0, 0, 0]]], dtype=uint32)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "nuclei = cle.voronoi_otsu_labeling(cle.top_hat_box(image, radius_x=5, radius_y=5), spot_sigma=1)\n", "nuclei\n" ] }, { "cell_type": "code", "execution_count": 5, "id": "e9daaab2-cef8-46d4-a129-636fff6283cc", "metadata": {}, "outputs": [], "source": [ "def move_stuff_around(image, nuclei, distance=1):\n", " \"\"\"\n", " Randomly move positions of given nuclei by applying a vector field to the image.\n", " \"\"\"\n", " centroids = cle.reduce_labels_to_centroids(nuclei)\n", " num_nuclei = nuclei.max()\n", " \n", " vector_field_x = make_random_vector_field(nuclei, distance)\n", " vector_field_y = make_random_vector_field(nuclei, distance)\n", " vector_field_z = make_random_vector_field(nuclei, distance)\n", "\n", " return cle.apply_vector_field(image, vector_field_x, vector_field_y, vector_field_z)\n", " \n", "\n", "def make_random_vector_field(nuclei, distance):\n", " \"\"\"\n", " Renerate a vector field from a label image by randomly introducing shift according to a given distance.\n", " \"\"\"\n", " random_shifts = (np.random.random((1, int(num_nuclei + 1))) * 2 -1) * distance\n", " random_shifts[0,0] = 0 # keep background where it is\n", "\n", " vector_field_sharp = cle.replace_intensities(nuclei, random_shifts)\n", " sigma = 10\n", " return cle.gaussian_blur(vector_field_sharp, sigma_x=sigma, sigma_y=sigma, sigma_z=sigma)\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "1e36aebb-3b96-4653-9d15-0ddc670e79aa", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "285.0" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "num_nuclei = nuclei.max()\n", "num_nuclei" ] }, { "cell_type": "code", "execution_count": 7, "id": "8177be2a-1921-4a5f-bb97-83379212dd43", "metadata": {}, "outputs": [], "source": [ "def analyze(image, nuclei):\n", "\n", " image_to_analyze = move_stuff_around(image, nuclei, distance=10)\n", " \n", " specific_nuclei = cle.voronoi_otsu_labeling(cle.top_hat_box(image_to_analyze, radius_x=5, radius_y=5), spot_sigma=1)\n", " \n", " mesh = cle.draw_mesh_between_proximal_labels(specific_nuclei, maximum_distance=25)\n", " \n", " \n", " return mesh * image_to_analyze.max()/4 + image_to_analyze\n", " " ] }, { "cell_type": "code", "execution_count": 8, "id": "6c1bcbbd-e81a-45ff-8d85-e81a6e2a7f67", "metadata": {}, "outputs": [], "source": [ "images = np.asarray([cle.maximum_z_projection(analyze(image, nuclei)) for i in range(10)])" ] }, { "cell_type": "code", "execution_count": 9, "id": "532c479c-40d6-4db5-9daa-bf3a025952f4", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Lossy conversion from float32 to uint8. Range [141.0, 813.0]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 813.0]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 812.25]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 813.0]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 805.25]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 813.0]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 813.0]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 813.0]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 812.25]. Convert image to uint8 prior to saving to suppress this warning.\n", "Lossy conversion from float32 to uint8. Range [141.0, 806.0]. Convert image to uint8 prior to saving to suppress this warning.\n" ] } ], "source": [ "save_as_animated_gif(images, \"visualization.gif\")" ] }, { "cell_type": "markdown", "id": "0d33480e-3ede-4cc6-9978-8150511eff95", "metadata": {}, "source": [ "![](visualization.gif)" ] }, { "cell_type": "code", "execution_count": 10, "id": "df1c68b5-d729-418f-afc2-8693b47046ba", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "451d4b48446141c2ac09f70db398e20d", "version_major": 2, "version_minor": 0 }, "text/plain": [ "VBox(children=(HBox(children=(VBox(children=(ImageWidget(height=256, width=256),)),)), IntSlider(value=5, desc…" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import stackview\n", "stackview.slice(np.asarray(images), continuous_update=True) " ] } ], "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.9.13" } }, "nbformat": 4, "nbformat_minor": 5 }