Draw distance-meshes between neighbors#

When studying neighborhood-relationships between cells, e.g. to determine if cells can communicate with each other, their distances to each other are relevant. We can visualize those using distance meshes.

import pyclesperanto_prototype as cle
from numpy import random
from skimage.io import imread

We’re using a dataset published by Heriche et al. licensed CC BY 4.0 available in the Image Data Resource.

raw_image = imread("../../data/plate1_1_013 [Well 5, Field 1 (Spot 5)].png")[:,:,0]

nuclei = cle.voronoi_otsu_labeling(raw_image, spot_sigma=15)

cle.imshow(nuclei, labels=True)
../_images/010a418108069486938af96db7cb13e0175786416345198f4e98d9a0df9d68dc.png

A mesh can for example be drawn between proximal neighbors, nuclei which are closer than a given maximum distance.

max_distance = 320

proximal_neighbor_mesh = cle.draw_mesh_between_proximal_labels(nuclei, maximum_distance=max_distance)

# we make the lines a bit thicker for visualization purposes
proximal_neighbor_mesh = cle.maximum_box(proximal_neighbor_mesh, radius_x=5, radius_y=5)

cle.imshow(proximal_neighbor_mesh)
../_images/50df103449f85897bafbe73a5da4cd240ea98a2693fb91957eac2463972df6be.png
proximal_distance_mesh = cle.draw_distance_mesh_between_proximal_labels(nuclei, maximum_distance=max_distance)

# we make the lines a bit thicker for visualization purposes
proximal_distance_mesh = cle.maximum_box(proximal_distance_mesh, radius_x=5, radius_y=5)

cle.imshow(proximal_distance_mesh)
../_images/9cc37b6a72541f57812e709f12bd0eb7712962951d529ffff6ec186167bcd4b9.png

Distance meshes in more detail#

For drawing a distance mesh, we need to combine a distance matrix, an abstract representation of distances of all objects to each other with a neighborhood-matrix, which represents which cells are neighbors.

We start with the distance matrix.

centroids = cle.centroids_of_background_and_labels(nuclei)

distance_matrix = cle.generate_distance_matrix(centroids, centroids)

# we ignor distances to the background object
cle.set_column(distance_matrix, 0, 0)
cle.set_row(distance_matrix, 0, 0)

cle.imshow(distance_matrix, colorbar=True)
../_images/4ef6505fa7103c0ce3ef963872a4cfa70ce0a61e2be9ba2740de96ea5b2488a1.png

Next, we should setup a matrix which represents for each nucleus (from the left to the right) which are its n nearest neighbors.

proximal_neighbor_matrix = cle.generate_proximal_neighbors_matrix(distance_matrix, max_distance=max_distance)

cle.imshow(proximal_neighbor_matrix)
../_images/aa3400095525196f732e9c0138d37eca94384c403d0abba7c23d05a43e33858a.png
distance_touch_matrix = distance_matrix * proximal_neighbor_matrix

cle.imshow(distance_touch_matrix, colorbar=True)
../_images/4f2e5cf35f71c0c5ac19ce6db917791d09aa4f6ae7cd5e1eea472c13e0019fb6.png
distance_mesh1 = cle.touch_matrix_to_mesh(centroids, distance_touch_matrix)

# we make the lines a bit thicker for visualization purposes
distance_mesh1 = cle.maximum_box(distance_mesh1, radius_x=5, radius_y=5)

cle.imshow(distance_mesh1, colorbar=True)
../_images/0007349ae6064e58d9a75a1d4fb6c3fc9ecf320ccae3d96c22f8827b22eaca59.png

To check if the nuclei from above are still the centroids of the mesh, we put both together in one image.

visualization = cle.maximum_images(nuclei > 0, distance_mesh1 > 0)

cle.imshow(visualization)
../_images/cede1d383e9956f09d5814b213496ed85b5ff09e74b232120f6100a363f245fe.png