Skip to content
This repository has been archived by the owner on Sep 27, 2023. It is now read-only.

Begin the porting to python #1

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions calculate_cell_positions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import numpy as np
import numpy.typing as npt

TWO_FIVE_FIVE = 255


def calculate_cell_positions(
image: npt.NDArray[np.float64], labelled_cells: npt.NDArray[np.uint16], type: bool
) -> None:
"""
This function calculates the min intensity position of each
labelled cell or the centroid position of each labelled region
"""
no_cells = labelled_cells.max()

pos = np.zeros((no_cells, 2))

subtracted_image = TWO_FIVE_FIVE - image

for n in range(no_cells):

sy, sx = np.argwhere(labelled_cells == n).T

if type:
_place_at_lowest_int(pos, subtracted_image, sx, sy, n)

else:
_place_at_centroid(pos, image, sx, sy, n)

if ~np.isnan(pos[n, 1]) and labelled_cells[pos[n, 1], pos[n, 0]] != n:
# every so often the centroid is actually not in the label!
_place_at_lowest_int(pos, image, sx, sy, n)

return pos


def _place_at_centroid(pos, image, sx, sy, n) -> None:
"""
calculating the centroid from intensities
"""
sum_x = 0
sum_y = 0
sum_I = 0

for m in range(len(sy)):
sum_x += sx[m] * image[sy[m], sx[m]]
sum_y += sy[m] * image[sy[m], sx[m]]
sum_I += image[sy[m], sx[m]]

pos[n, 1] = round(sum_y / sum_I)
pos[n, 0] = round(sum_x / sum_I)
return pos


def _place_at_lowest_int(pos, image, sx, sy, n) -> None:
"""
looking for the lowest intensity
"""
val = TWO_FIVE_FIVE

for m in range(len(sy)):

if image[sy[m], sx[m]] < val:

val = image[sy[m], sx[m]]
pos[n, 2] = sy[m]
pos[n, 1] = sx[m]
41 changes: 41 additions & 0 deletions example_segmentation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from pathlib import Path

from scipy import io as sio
from skimage.morphology import disk

from segment_image import segment_image
from utils import unlabel_poor_seeds_in_frame

_file_location = Path(__file__).resolve()
_matfile = _file_location.parent / "ProjIm.mat"


def main() -> None:
"""
implements the demo in the README in python
"""
# load example image (Projected Drosophila Wing Disc - Ecad:GFP)
proj_im = sio.loadmat(_matfile)["ProjIm"]

# crop image for testing
cropped_image = proj_im[300:500, 400:600]

segmentation, seeds, labels = segment_image(
cropped_image,
sigma_1=0.5,
min_cell_size=2,
threshold=20,
merge_criteria=0.0,
sigma_3=0.5,
large_cell_size_thres=3000,
I_bound_max_pcnt=0.1,
show_feedback=True,
)


if __name__ == "__main__":
se = disk(2)
Im = sio.loadmat(_file_location.parent / "Im.mat")["Im"]
CellSeeds = sio.loadmat(_file_location.parent / "CellSeeds.mat")["CellSeeds"]
CellLabels = sio.loadmat(_file_location.parent / "CellLabels.mat")["CellLabels"]
unlabel_poor_seeds_in_frame(Im, CellSeeds, CellLabels, se, 20, 0.5, 0.1),
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
numpy==1.23.1
scikit-image==0.19.3
scipy==1.9.0
86 changes: 86 additions & 0 deletions segment_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import numpy as np
import numpy.typing as npt
from skimage.morphology import disk

from utils import (
create_color_boundaries,
do_initial_seeding,
grow_cells_in_frame,
merge_seeds_from_labels,
neutralise_pts_not_under_label_in_frame,
unlabel_poor_seeds_in_frame,
)


def segment_image(
image: npt.NDArray[np.uint8],
*,
sigma_1: float,
min_cell_size: float,
threshold: int,
merge_criteria: float,
sigma_3: float,
large_cell_size_thres: float,
I_bound_max_pcnt: float,
show_feedback: bool = False
) -> tuple[npt.NDArray[np.uint8], npt.NDArray[np.uint8], npt.NDArray[np.uint16]]:
"""
Segments a single frame extracting the cell outlines.

Args:
image:
increasing intesity for membrane
sigma_1:
size px of gaussian for smoothing image [0+]
min_cell_size:
size px of smallest cell expected [0+]
threshold:
minimum value for membrane signal [0-255]
merge_criteria:
minimum ratio of low intensity pxs upon which to merge cells [0-1]
sigma_3:
size px of gaussian for smoothing image [0+]
large_cell_size_thres:
size px of largest cell expected [0+]
I_bound_max_pcnt:
minimum ratio for seed and membrane intensity [0-1]
show_feedback:
show feedback for segmentation

Returns:
segmented_image:
Im with seeds [255] and cell outlines [0]
cell_seeds:
Rescaled Image to fit the range [0,252]
253/254/255 are used for seed information
cell_labels:
bitmap of cells colored with 16bit id
"""
# initialise
cell_seeds = np.zeros(image.shape, dtype=np.uint8)
# TODO: why using 16 bit for labels?
cell_labels = np.zeros(image.shape, dtype=np.uint16)

# TODO: check image casting
image = image.astype(float)
image *= 252 / image.max()
image = image.astype(np.uint8)

# structuring element, SE, used for morphological operations
se = disk(2)

do_initial_seeding(image, sigma_1, min_cell_size, threshold, large_cell_size_thres)

merge_seeds_from_labels(image, cell_seeds, cell_labels, se, merge_criteria, sigma_3)

grow_cells_in_frame(image, cell_seeds, sigma_3)

unlabel_poor_seeds_in_frame(
image, cell_seeds, cell_labels, se, threshold, sigma_3, I_bound_max_pcnt
)

neutralise_pts_not_under_label_in_frame(cell_seeds, cell_labels)

create_color_boundaries(image, cell_seeds, cell_labels)

return image, cell_seeds, cell_labels
8 changes: 8 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[flake8]
ignore = E203,E741,W503,W605
max-complexity = 18
max-line-length = 88
select = B,B9,BLK,C,E,F,I,S,T4,W

[mypy]
plugins = numpy.typing.mypy_plugin
Loading