The notebook shows how to load an IDR image with labels.
The image is referenced in the paper "NesSys: a novel method for accurate nuclear segmentation in 3D" published August 2019 in PLOS Biology: https://doi.org/10.1371/journal.pbio.3000388 and can be viewed online in the Image Data Resource.
In this notebook, the image is loaded together with the labels and analyzed using StarDist. The StarDist analysis produces a segmentation, which is then viewed side-by-side with the original segmentations produced by the authors of the paper obtained via the loaded labels.
If you wish to run the notebook locally or run the corresponding Python script, please read instruction in README.
The cell below will install dependencies if you choose to run the notebook in Google Colab.
%pip install omero-py stardist geojson
Requirement already satisfied: omero-py in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (5.11.0) Requirement already satisfied: stardist in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (0.8.1) Requirement already satisfied: geojson in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (2.5.0) Requirement already satisfied: future in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (0.18.2) Requirement already satisfied: Pillow in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (9.0.1) Requirement already satisfied: appdirs in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (1.4.4) Requirement already satisfied: requests in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (2.27.1) Requirement already satisfied: numpy in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (1.21.5) Requirement already satisfied: PyYAML in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (6.0) Requirement already satisfied: zeroc-ice<3.7,>=3.6.4 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from omero-py) (3.6.5) Requirement already satisfied: numba in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from stardist) (0.55.1) Requirement already satisfied: imageio in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from stardist) (2.16.1) Requirement already satisfied: csbdeep>=0.6.3 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from stardist) (0.6.3) Requirement already satisfied: scikit-image in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from stardist) (0.19.2) Requirement already satisfied: h5py>=3 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from csbdeep>=0.6.3->stardist) (3.6.0) Requirement already satisfied: tifffile in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from csbdeep>=0.6.3->stardist) (2022.3.25) Requirement already satisfied: tqdm in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from csbdeep>=0.6.3->stardist) (4.63.1) Requirement already satisfied: six in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from csbdeep>=0.6.3->stardist) (1.16.0) Requirement already satisfied: matplotlib in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from csbdeep>=0.6.3->stardist) (3.5.1) Requirement already satisfied: scipy in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from csbdeep>=0.6.3->stardist) (1.8.0) Requirement already satisfied: llvmlite<0.39,>=0.38.0rc1 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from numba->stardist) (0.38.0) Requirement already satisfied: setuptools in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from numba->stardist) (61.2.0) Requirement already satisfied: certifi>=2017.4.17 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from requests->omero-py) (2021.10.8) Requirement already satisfied: charset-normalizer~=2.0.0 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from requests->omero-py) (2.0.12) Requirement already satisfied: urllib3<1.27,>=1.21.1 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from requests->omero-py) (1.26.9) Requirement already satisfied: idna<4,>=2.5 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from requests->omero-py) (3.3) Requirement already satisfied: packaging>=20.0 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from scikit-image->stardist) (21.3) Requirement already satisfied: PyWavelets>=1.1.1 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from scikit-image->stardist) (1.3.0) Requirement already satisfied: networkx>=2.2 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from scikit-image->stardist) (2.7.1) Requirement already satisfied: pyparsing!=3.0.5,>=2.0.2 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from packaging>=20.0->scikit-image->stardist) (3.0.7) Requirement already satisfied: fonttools>=4.22.0 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from matplotlib->csbdeep>=0.6.3->stardist) (4.31.2) Requirement already satisfied: kiwisolver>=1.0.1 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from matplotlib->csbdeep>=0.6.3->stardist) (1.4.2) Requirement already satisfied: python-dateutil>=2.7 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from matplotlib->csbdeep>=0.6.3->stardist) (2.8.2) Requirement already satisfied: cycler>=0.10 in /Users/jmarie/opt/anaconda3/envs/stardist/lib/python3.9/site-packages (from matplotlib->csbdeep>=0.6.3->stardist) (0.11.0) Note: you may need to restart the kernel to use updated packages.
from omero.gateway import BlitzGateway
import matplotlib.pyplot as plt
%matplotlib inline
import numpy
HOST = 'ws://idr.openmicroscopy.org/omero-ws'
conn = BlitzGateway('public', 'public',
host=HOST, secure=True)
print(conn.connect())
conn.c.enableKeepAlive(60)
True
image_id = 6001247
image = conn.getObject("Image", image_id)
The image is loaded a TCZYX numpy array to match the Zarr file.
def load_numpy_array(image):
pixels = image.getPrimaryPixels()
size_z = image.getSizeZ()
size_c = image.getSizeC()
size_t = image.getSizeT()
size_y = image.getSizeY()
size_x = image.getSizeX()
z, t, c = 0, 0, 0 # first plane of the image
zct_list = []
for t in range(size_t):
for c in range(size_c): # all channels
for z in range(size_z): # get the Z-stack
zct_list.append((z, c, t))
values = []
# Load all the planes as YX numpy array
planes = pixels.getPlanes(zct_list)
s = "t:%s c:%s z:%s y:%s x:%s" % (size_t, size_c, size_z, size_y, size_x)
print(s)
print("Downloading image %s" % image.getName())
all_planes = numpy.stack(list(planes))
shape = (size_t, size_c, size_z, size_y, size_x)
return numpy.reshape(all_planes, newshape=shape)
data = load_numpy_array(image)
t:1 c:2 z:257 y:210 x:253 Downloading image B4_C3.tif
Labels have been saved as mask.
from omero_zarr import masks
roi_service = conn.getRoiService()
result = roi_service.findByImage(image_id, None)
dims = (image.getSizeT(), image.getSizeC(), image.getSizeZ(), image.getSizeY(), image.getSizeX())
shapes = []
for roi in result.rois:
shapes.append(roi.copyShapes())
saver = masks.MaskSaver(None, image, numpy.int64)
labels, fillColors, properties = saver.masks_to_labels(shapes, mask_shape=dims)
print(labels.shape)
(1, 2, 257, 210, 253)
from stardist.models import StarDist2D
model_versatile = StarDist2D.from_pretrained('2D_demo')
Found model '2D_demo' for 'StarDist2D'. Loading network weights from 'weights_best.h5'. Loading thresholds from 'thresholds.json'. Using default values: prob_thresh=0.486166, nms_thresh=0.5.
2022-04-22 13:25:38.405162: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: SSE4.1 SSE4.2 To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Normalize the input image
model_versatile.predict_instances
will
from csbdeep.utils import normalize
from geojson import Feature, FeatureCollection, Polygon
axis_norm = (0,1)
c = 1
img = normalize(data[0, c, :, :, :], 1,99.8, axis=axis_norm)
results = []
shapes = []
for i in range(len(img)):
new_labels, details = model_versatile.predict_instances(img[i])
# Convert into Polygon and add to Geometry Collection
for obj_id, region in enumerate(details['coord']):
coordinates = []
x = region[1]
y = region[0]
for j in range(len(x)):
coordinates.append((float(x[j]), float(y[j])))
# append the first coordinate to close the polygon
coordinates.append(coordinates[0])
shape = Polygon(coordinates)
properties = {
"stroke-width": 1,
"z": i,
"c": c,
}
shapes.append(Feature(geometry=shape, properties=properties))
results.append(new_labels)
label_slices = numpy.array(results)
gc = FeatureCollection(shapes)
Save the labels locally in a machine and human readable format: geojson.
Stardist offers method to save the labels into ImageJ rois using export_imagej_rois
. This is outside the scope of this notebook.
# Save the shapes as geojson
import geojson
geojson_file = "stardist_shapes_%s.geojson" % image_id
geojson_dump = geojson.dumps(gc, sort_keys=True)
with open(geojson_file, 'w') as out:
out.write(geojson_dump)
Display the original labels and the labels based on StarDist prediction side-by-side
from ipywidgets import *
def update(z=0):
c = 1
fig = plt.figure(figsize=(10, 10))
plt.subplot(121)
plt.imshow(data[0, c, z, :, :], cmap='gray')
try:
plt.imshow(labels[0, c, z, :, :], cmap='jet', alpha=0.5)
except Exception:
print(z)
plt.subplot(122)
plt.imshow(data[0, c, z, :, :], cmap='gray')
plt.imshow(label_slices[z, :, :], cmap='jet', alpha=0.5)
plt.tight_layout()
fig.canvas.flush_events()
interact(update, z= widgets.IntSlider(value=1, min=0, max=data.shape[2]-1, step=1, description="Select Z", continuous_update=False))
interactive(children=(IntSlider(value=1, continuous_update=False, description='Select Z', max=256), Output()),…
<function __main__.update(z=0)>
conn.close()
Copyright (C) 2022 University of Dundee. All Rights Reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 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. 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.