import copy
import numpy as np
import os
from tifffile import imread, imwrite
import skimage.color as skcolor
import seaborn as sns
from skimage.segmentation import relabel_sequential
[docs]
class manual_curate_segmentation():
"""
This class provides functions to manually curate images
"""
[docs]
def remove_label(self, stack, label):
"""
Removes a specific label from a 3D image stack.
:param stack: numpy array
:param label: label
:return: processed numpy array
"""
currentlabel_indices = np.where(stack == label)
stack[currentlabel_indices] = 0
return stack
[docs]
def merge_label(self, stack, label1, label2):
"""
Merge labels (replaces label2 with label1)
:param stack: numpy array to process
:param label1: integer label
:param label2: integer label
:return: processed numpy array
"""
currentlabel_indices = np.where(stack == label2)
stack[currentlabel_indices] = label1
return stack
[docs]
def takeLabel_fromanotherstack(self, stack, anotherstack, label):
"""
Take a label from another stack (anotherstack) and insert it into the current stack (stack).
:param stack: numpy array to process
:param anotherstack: numpy array to take label from
:param label: label to take
:return: processed numpy array
"""
anotherstack_indices = np.where(anotherstack == label)
maximumlabel = np.max(stack)
newlabel = anotherstack[anotherstack_indices] + maximumlabel + 1
stack[anotherstack_indices] = anotherstack[anotherstack_indices] + maximumlabel + 1
return stack, newlabel[0]
[docs]
def takeLabel_fromanotherstack_range(self, stack, anotherstack_orig, label, xrange=[], yrange=[], zrange=[]):
"""
Take a label from another stack (anotherstack) and insert it into the current stack (stack).
:param stack: numpy array to process
:param anotherstack: numpy array to take label from
:param label: label to take
:param xrange: narrow down where to take the label from (range in x/shape[1])
:param yrange: narrow down where to take the label from (range in y/shape[2])
:param zrange: narrow down where to take the label from (range in z/shape[0])
:return: processed numpy array
"""
anotherstack = copy.deepcopy(anotherstack_orig)
if not zrange:
zrange = [0, anotherstack.shape[0]]
if not xrange:
xrange = [0, anotherstack.shape[1]]
if not yrange:
yrange = [0, anotherstack.shape[2]]
#make boundingbox and bound image
binarybox = np.zeros(anotherstack.shape)
binarybox[zrange[0]:zrange[1], xrange[0]:xrange[1], yrange[0]:yrange[1]]=1
selectedimage = binarybox * anotherstack
#select only specific labels
anotherstack_indices = np.where(selectedimage == label)
maximumlabel = np.max(stack)
newlabel = anotherstack[anotherstack_indices] + maximumlabel + 1
stack[anotherstack_indices] = anotherstack_orig[anotherstack_indices] + maximumlabel + 1
return stack, newlabel[0]
[docs]
def replace_one_label(self, stack, anotherstack, labeltoreplace):
"""
Replace all positions in a stack with a defined label (labeltoreplace) with unique labels of anotherstack at these positions.
:param stack: np.array to replace a label
:param anotherstack: take the label id from this stack for all position with labeltoreplace in stack
:param labeltoreplace: label to replace
:return: modified stack
"""
# make binary 0 or 1
im_binary = anotherstack > 0.5
currentlabel_indices = np.where(stack == labeltoreplace)
maximumlabel = np.max(stack)
stack[currentlabel_indices] = im_binary[currentlabel_indices] * (anotherstack[currentlabel_indices] + maximumlabel + 1)
return stack
[docs]
def give_label_new_identiyinarea(self, stack, label, xrange=[], yrange=[], zrange=[]):
"""
Find a label in (xrange, yrange, zrange) and give it a new unique label
:param stack: numpy array to process
:param label: label to modify
:param xrange: narrow down where to modify the label (range in x/shape[1])
:param yrange: narrow down where to modify the label (range in y/shape[2])
:param zrange: narrow down where to modify the label (range in z/shape[0])
:return: modified np.array, new unique label
"""
anotherstack = copy.deepcopy(stack)
if not zrange:
zrange = [0, anotherstack.shape[0]]
if not xrange:
xrange = [0, anotherstack.shape[1]]
if not yrange:
yrange = [0, anotherstack.shape[2]]
# make boundingbox and bound image
binarybox = np.zeros(anotherstack.shape)
binarybox[zrange[0]:zrange[1], xrange[0]:xrange[1], yrange[0]:yrange[1]] = 1
selectedimage = binarybox * anotherstack
# select only specific labels
anotherstack_indices = np.where(selectedimage == label)
maximumlabel = np.max(stack)
newlabel = anotherstack[anotherstack_indices] + maximumlabel + 1
stack[anotherstack_indices] = stack[anotherstack_indices] + maximumlabel + 1
return stack, newlabel[0]
[docs]
def saveimage(self, new_image, path_save, path_save_RGB):
"""
Save the image to disk
:param new_image: image to save
:param path_save: path to save label image
:param path_save_RGB: path to save label image with RGB color labels.
"""
# relabel image so that labels go from 1 to x
relab, fw2, inv2 = relabel_sequential(new_image)
# save new curated
imwrite(path_save, relab)
color_image = np.uint8(255 * skcolor.label2rgb(relab.copy(),
colors=sns.color_palette('hls', n_colors=16),
bg_label=0))
imwrite(path_save_RGB, np.uint8(color_image))
if __name__ == "__main__":
# =============================================================================
# initializations
# =============================================================================
region = "high_stack_002"
timepoint = "t00049"
parentfolder = "/archive/bioinformatics/Danuser_lab/Fiolka/LabMembers/Stephan/multiscale_data/xenograft_experiments/U2OS_WT/20220729_Daetwyler_U2OS"
data_segmentation = os.path.join(parentfolder, "Experiment0001_highresSeg_connectedComp_multiOtsu", "processed_segmentation_merged130", region, timepoint, "labels_xy-merged.tif")
data_before_processing = os.path.join(parentfolder, "Experiment0001_highresSeg_connectedComp_multiOtsu", "result_segmentation", region, timepoint, "labels_xy-connectedcomponents.tif")
data_cellpose = os.path.join(parentfolder, "Experiment0001_highresSeg_run_again", "result_segmentation", region, timepoint, "labels_xy-integrated_gradients-correct_noexpand.tif")
data_segmentation = os.path.join(parentfolder, "Experiment0001_highres_manuallyCompiled", region, timepoint, "labels_xy-merged.tif")
path_save_folder = os.path.join(parentfolder, "Experiment0001_highres_manuallyCompiled2", region, timepoint)
path_save = os.path.join(path_save_folder, "labels_xy-merged.tif")
path_save_RGB = os.path.join(path_save_folder, "labels_xy-merged_componentsRGB.tif")
try:
os.makedirs(path_save_folder)
except OSError as error:
pass
"""parameters"""
curate_it = manual_curate_segmentation()
new_image = imread(data_segmentation)
multiOtsu_segmentation = imread(data_before_processing)
cellpose_segmentation = imread(data_cellpose)
# example t00027
# new_image = curate_it.merge_label(new_image, 17, 20)
# new_image = curate_it.merge_label(new_image, 14, 26)
# new_image = curate_it.merge_label(new_image, 21, 22)
# new_image, newlabel = curate_it.takeLabel_fromanotherstack(new_image, cellpose_segmentation, 100)
# new_image = curate_it.merge_label(new_image, 24, newlabel)
# new_image = curate_it.replace_one_label(new_image, cellpose_segmentation, 23)
# save image
curate_it.saveimage(new_image, path_save, path_save_RGB)