Source code for abm_colony_collection.get_depth_map
import numpy as np
from scipy import ndimage
from skimage import measure
[docs]def get_depth_map(array: np.ndarray, neighbors_map: dict) -> dict:
"""
Get map of id to depth starting from depth = 1 at the edge if the region.
All ids at the edge of the array are assigned a depth of 1. Immediate
neighbors of those edges are assigned a depth of 2, and so on, until all ids
have an assigned depth.
Parameters
----------
array
Segmentation array.
neighbors_map
Map of ids to lists of neighbors.
Returns
-------
:
Map of id to depth from edge.
"""
depth_map = {cell_id: 0 for cell_id in np.unique(array)}
depth_map.pop(0, None)
# Return empty depth map if there are no cell ids in the array
if not depth_map:
return depth_map
edge_ids = find_edge_ids(array)
visited = set(edge_ids)
queue = edge_ids.copy()
while queue:
current_id = queue.pop(0)
current_neighbors = neighbors_map[current_id]["neighbors"]
valid_neighbors = set(current_neighbors) - visited
visited.update(valid_neighbors)
queue = queue + list(valid_neighbors)
for neighbor_id in valid_neighbors:
depth_map[neighbor_id] = depth_map[current_id] + 1
depth_map[current_id] = depth_map[current_id] + 1
return depth_map
[docs]def find_edge_ids(array: np.ndarray) -> list[int]:
"""
Get ids of regions closest to the edge of the array.
Parameters
----------
array
Segmentation array.
Returns
-------
:
List of edge arrays.
"""
slice_index = np.argmax(np.count_nonzero(array, axis=(1, 2)))
array_slice = array[slice_index, :, :]
# Calculate voronoi from cell shapes.
distances = ndimage.distance_transform_edt(
array_slice == 0, return_distances=False, return_indices=True
)
distances = distances.astype("uint16", copy=False)
coordinates_y = distances[0].flatten()
coordinates_x = distances[1].flatten()
voronoi = array_slice[coordinates_y, coordinates_x].reshape(array_slice.shape)
# Create border mask.
mask = np.zeros(array_slice.shape, dtype="uint8")
mask[array_slice != 0] = 1
while measure.euler_number(mask) != 1:
mask = ndimage.binary_dilation(mask, iterations=1)
# Filter voronoi by mask to get edge ids.
voronoi[mask == 1] = 0
edge_ids = list(np.unique(voronoi))
edge_ids.remove(0)
return edge_ids