def Workflow_template(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: ########################################################################## ################### # PRE_PROCESSING # make sure the variable name of original image is 'struct_img' ################### # intenisty normalization # smoothing ################### # core algorithm ################### ################### # POST-PROCESSING # make sure the variable name of final segmentation is 'seg' ################### ########################################################################## # ## no need to change below ########################################################################## # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 if output_type == "default": # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: print("your can implement your output hook here, but not yet") quit()
def Workflow_lmnb1_interphase( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure LMNB1 interphase Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[1, 0.01], [2, 0.01], [3, 0.01]] hole_max = 40000 hole_min = 400 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # rescale if needed if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range, ) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # get the mid frame mid_z = get_middle_frame(structure_img_smooth, method="intensity") # 2d filament filter on the middle frame bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param) # hole filling bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max) seed = get_3dseed_from_mid_frame( np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z, hole_min, bg_seed=True, ) seg_filled = ( watershed(struct_img, seed.astype(int), watershed_line=True) > 1 ) # in watershed result, 1 is for background # get the actual shell seg = find_boundaries(seg_filled, connectivity=1, mode="thick") # output seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def RAB5A_HiPSC_Pipeline(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [6000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_3d_sigma = 1 dot_3d_cutoff = 0.02 minArea = 5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: LOG 3d response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) bw = response > dot_3d_cutoff bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) out_img_list.append(bw.copy()) out_name_list.append('interm_mask') # step 2: 'local_maxi + watershed' for cell cutting local_maxi = peak_local_max(struct_img,labels=label(bw), min_distance=2, indices=False) out_img_list.append(local_maxi.copy()) out_name_list.append('interm_local_max') distance = distance_transform_edt(bw) im_watershed = watershed(-distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True) ################### # POST-PROCESSING ################### seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for other pre-defined RnD output functions (AICS internal) RAB5A_output(out_img_list, out_name_list, output_type, output_path, fn)
def Workflow_atp2a2(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [2.5, 9.0] vesselness_sigma = [1] vesselness_cutoff = 0.25 minArea = 15 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # 2d vesselness slice by slice response = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) bw = response > vesselness_cutoff ################### # POST-PROCESSING ################### bw = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) for zz in range(bw.shape[0]): bw[zz, :, :] = remove_small_objects(bw[zz, :, :], min_size=3, connectivity=1, in_place=False) seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = SEC61B_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_cardio_npm1_100x( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure Cardio NPM1 100x Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [0.5, 2.5] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_2d_sigma = 2 # dot_2d_sigma_extra = 1 # dot_2d_cutoff = 0.025 minArea = 1 low_level_min_size = 1000 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # rescale if needed if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = ( gaussian_smoothing_truncate_range * rescale_ratio) # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range, ) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # step 1: low level thresholding # global_otsu = threshold_otsu(structure_img_smooth) global_tri = threshold_triangle(structure_img_smooth) global_median = np.percentile(structure_img_smooth, 50) th_low_level = (global_tri + global_median) / 2 # print(global_median) # print(global_tri) # print(th_low_level) # imsave('img_smooth.tiff', structure_img_smooth) bw_low_level = structure_img_smooth > th_low_level bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) bw_low_level = dilation(bw_low_level, selem=ball(2)) # step 2: high level thresholding local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) bw_high_level = np.zeros_like(bw_low_level) lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) for idx in range(num_obj): single_obj = lab_low == (idx + 1) local_otsu = threshold_otsu(structure_img_smooth[single_obj]) if local_otsu > local_cutoff: bw_high_level[np.logical_and( structure_img_smooth > 1.2 * local_otsu, single_obj)] = 1 # imsave('seg_coarse.tiff', bw_high_level.astype(np.uint8)) out_img_list.append(bw_high_level.copy()) out_name_list.append("bw_coarse") response_bright = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) bw_extra = response_bright > 0.03 # dot_2d_cutoff bw_extra[~bw_low_level] = 0 bw_final = np.logical_or(bw_extra, bw_high_level) # bw_final[holes]=0 ################### # POST-PROCESSING ################### seg = remove_small_objects(bw_final, min_size=minArea, connectivity=1, in_place=True) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_drug_npm1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [0.5, 25] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_2d_sigma = 1 dot_2d_cutoff = 0.01 minArea = 5 low_level_min_size = 700 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: low level thresholding #global_otsu = threshold_otsu(structure_img_smooth) global_tri = threshold_triangle(structure_img_smooth) global_median = np.percentile(structure_img_smooth,50) th_low_level = (global_tri + global_median)/2 bw_low_level = structure_img_smooth > th_low_level bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) # step 2: high level thresholding bw_high_level = np.zeros_like(bw_low_level) lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) for idx in range(num_obj): single_obj = (lab_low==(idx+1)) local_otsu = threshold_otsu(structure_img_smooth[single_obj]) bw_high_level[np.logical_and(structure_img_smooth>local_otsu, single_obj)]=1 out_img_list.append(bw_high_level.copy()) out_name_list.append('interm_high') # step 3: finer segmentation # response2d = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) # bw_finer = remove_small_objects(response2d>dot_2d_cutoff, min_size=minArea, connectivity=1, in_place=True) bw_finer = dot_3d_wrapper(structure_img_smooth, s3_param = [[1, 0.015]]) out_img_list.append(bw_finer.copy()) out_name_list.append('bw_fine') # merge finer level detection into high level coarse segmentation to include outside dim parts bw_high_level[bw_finer>0]=1 ################### # POST-PROCESSING ################### seg = remove_small_objects(bw_high_level>0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_coarse') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_npm1(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [0.5, 15] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_2d_sigma = 2 dot_2d_sigma_extra = 1 dot_2d_cutoff = 0.025 minArea = 5 low_level_min_size = 700 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: low level thresholding #global_otsu = threshold_otsu(structure_img_smooth) global_tri = threshold_triangle(structure_img_smooth) global_median = np.percentile(structure_img_smooth, 50) th_low_level = (global_tri + global_median) / 2 bw_low_level = structure_img_smooth > th_low_level bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) bw_low_level = dilation(bw_low_level, selem=ball(2)) # step 2: high level thresholding local_cutoff = 0.333 * threshold_otsu(structure_img_smooth) bw_high_level = np.zeros_like(bw_low_level) lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) for idx in range(num_obj): single_obj = (lab_low == (idx + 1)) local_otsu = threshold_otsu(structure_img_smooth[single_obj]) if local_otsu > local_cutoff: bw_high_level[np.logical_and( structure_img_smooth > 0.98 * local_otsu, single_obj)] = 1 out_img_list.append(bw_high_level.copy()) out_name_list.append('bw_coarse') response_bright = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) response_dark = dot_slice_by_slice(1 - structure_img_smooth, log_sigma=dot_2d_sigma) response_dark_extra = dot_slice_by_slice(1 - structure_img_smooth, log_sigma=dot_2d_sigma_extra) #inner_mask = bw_high_level.copy() #for zz in range(inner_mask.shape[0]): # inner_mask[zz,:,:] = binary_fill_holes(inner_mask[zz,:,:]) holes = np.logical_or(response_dark > dot_2d_cutoff, response_dark_extra > dot_2d_cutoff) #holes[~inner_mask] = 0 bw_extra = response_bright > dot_2d_cutoff #bw_extra[~bw_high_level]=0 bw_extra[~bw_low_level] = 0 bw_final = np.logical_or(bw_extra, bw_high_level) bw_final[holes] = 0 ################### # POST-PROCESSING ################### seg = remove_small_objects(bw_final, min_size=minArea, connectivity=1, in_place=True) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_fine') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = NPM1_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_pxn(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [11, 8] vesselness_sigma = [1] vesselness_cutoff = 0.35 minArea3D = 15 minArea2D = 4 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # vesselness 3d response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) bw = response > vesselness_cutoff ################### # POST-PROCESSING ################### seg = np.zeros_like(bw) for zz in range(bw.shape[0]): seg[zz, :, :] = remove_small_objects(bw[zz, :, :] > 0, min_size=minArea2D, connectivity=1, in_place=False) seg = remove_small_objects(seg > 0, min_size=minArea3D, connectivity=1, in_place=False) # determine z-range bw_z = np.zeros(bw.shape[0], dtype=np.uint16) for zz in range(bw.shape[0]): bw_z[zz] = np.count_nonzero(seg[zz, :, :] > 0) mid_z = np.argmax(bw_z) low_z = 0 high_z = seg.shape[0] - 2 for ii in np.arange(mid_z - 1, 0, -1): if bw_z[ii] < 100: low_z = ii break for ii in range(mid_z + 1, bw.shape[0] - 1, 1): if bw_z[ii] < 100: high_z = ii break seg[:low_z, :, :] = 0 seg[high_z + 1:, :, :] = 0 # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = PXN_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_lamp1( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure LAMP1 Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_scaling_param = [3, 19] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 minArea = 15 # ves_th_2d = 0.1 vesselness_sigma = [1] vesselness_cutoff = 0.15 # hole_min = 60 hole_max = 1600 log_sigma_1 = 5 log_cutoff_1 = 0.09 log_sigma_2 = 2.5 log_cutoff_2 = 0.07 log_sigma_3 = 1 log_cutoff_3 = 0.01 ########################################################################## out_img_list = [] out_name_list = [] # intenisty normalization struct_img = intensity_normalization( struct_img, scaling_param=intensity_scaling_param ) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / ( struct_img.max() - struct_img.min() + 1e-8 ) gaussian_smoothing_truncate_range = ( gaussian_smoothing_truncate_range * rescale_ratio ) structure_img_smooth = image_smoothing_gaussian_slice_by_slice( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range, ) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") # spot detection response1 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_1) bw1 = response1 > log_cutoff_1 response2 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_2) bw2 = response2 > log_cutoff_2 bw_spot = np.logical_or(bw1, bw2) response3 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_3) bw3 = response3 > log_cutoff_3 bw_spot = np.logical_or(bw_spot, bw3) # ring/filament detection ves = vesselnessSliceBySlice( structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True ) bw_ves = ves > vesselness_cutoff # fill holes partial_fill = np.logical_or(bw_spot, bw_ves) out_img_list.append(partial_fill.copy()) out_name_list.append("interm_before_hole") holes = np.zeros_like(partial_fill) for zz in range(partial_fill.shape[0]): background_lab = label(~partial_fill[zz, :, :], connectivity=1) out = np.copy(background_lab) component_sizes = np.bincount(background_lab.ravel()) too_big = component_sizes > hole_max too_big_mask = too_big[background_lab] out[too_big_mask] = 0 # too_small = component_sizes <hole_min # too_small_mask = too_small[background_lab] # out[too_small_mask] = 0 holes[zz, :, :] = out full_fill = np.logical_or(partial_fill, holes) seg = remove_small_objects( full_fill, min_size=minArea, connectivity=1, in_place=False ) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_npm1_bright_v3_single(struct_img, mitotic_stage, rescale_ratio, output_type, output_path, fn, output_func=None): ''' no high level thresholindg is used - step2 ''' ########################################################################## # Basic PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [15, 5] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_2d_sigma = 2 dot_2d_sigma_extra = 3 minArea = 8 low_level_min_size = 300 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio structure_img_smooth = edge_preserving_smoothing_3d(struct_img, numberOfIterations=10, conductance=1.2, timeStep=0.0625) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # mitotic stage should align to folder name mito_seed_path_root = "/allen/aics/assay-dev/computational/data/Nucleus_structure_segmentation/trainset/NPM1_norm1/mem/" mito_seed_path = mito_seed_path_root + fn.replace('.tiff', '.mem_seg.tiff') # # mito_seed_path_root = "/allen/aics/assay-dev/computational/data/Nucleus_structure_segmentation/fibrillarin_segmentation_improvement/" + mitotic_stage + "/mito_seg/" # # mito_seed_path = mito_seed_path_root + fn + "_mem_segmentation.tif" # # Generate seed for mitotic cell mito_3d = imread(mito_seed_path) if np.ndim(mito_3d) == 4: mito_3d = mito_3d[:, :, :, 0] # specific case for presentation # mito_seed_path_root = '/allen/aics/assay-dev/computational/data/Nucleus_structure_segmentation/presentation/mem_seg/FBL_NPM1/' # mito_seed_path = mito_seed_path_root + fn.replace('.czi', '_mem_segmentation.tiff') # mito_3d = imread(mito_seed_path) # mito_3d = (mito_3d == 2).astype(np.uint8) ############################### bw_high_level = np.zeros_like(mito_3d) # lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) object_img = structure_img_smooth[mito_3d > 0] local_cutoff = threshold_otsu(structure_img_smooth) otsu_mito = threshold_otsu(structure_img_smooth[mito_3d > 0]) # pdb.set_trace() local_diff = (local_cutoff - otsu_mito) adaptive_factor = 0 local_otsu = 0 # vessel_cutoff = 0.95 # slice_cutoff = 0.03 # local_otsu = 1.9 * otsu_mito # It was 0.13 # bw_high_level[np.logical_and(structure_img_smooth> local_otsu, mito_3d>0)]=1 # bw_high_level = dilation(bw_high_level, selem=ball(1.5)) if local_diff >= 0.33: vessel_cutoff = 0.045 slice_cutoff = 0.03 elif local_diff >= 0.10 and local_diff < 0.33: vessel_cutoff = 0.105 slice_cutoff = 0.04 local_otsu = 2.1 * otsu_mito bw_high_level[np.logical_and(structure_img_smooth > local_otsu, mito_3d > 0)] = 1 # When FBL seg is very brgiht elif local_diff < 0.05: vessel_cutoff = 0.15 slice_cutoff = 0.06 local_otsu = 2.5 * otsu_mito bw_high_level[np.logical_and(structure_img_smooth > local_otsu, mito_3d > 0)] = 1 # if local_diff >= 0.15: # vessel_cutoff = 0.04 # slice_cutoff = 0.02 # # When FBL seg is very brgiht # elif local_diff < 0.05: # vessel_cutoff = 0.105 # slice_cutoff = 0.03 # local_otsu = 1.7 * otsu_mito # bw_high_level[np.logical_and(structure_img_smooth> local_otsu, mito_3d>0)]=1 # print(local_diff, local_otsu, np.percentile(structure_img_smooth[mito_3d>0],25)) res3 = vesselnessSliceBySlice(structure_img_smooth, [1], tau=0.5, whiteonblack=True) res1 = dot_slice_by_slice(structure_img_smooth, 2) response_bright = np.logical_or(res1 > slice_cutoff, res3 > vessel_cutoff) total_bright = np.logical_or(response_bright, bw_high_level) bw_final = total_bright # pdb.set_trace() ################### # POST-PROCESSING ################### seg = remove_small_objects(bw_final, min_size=minArea, connectivity=1, in_place=True) seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_fine') fn = fn + "_npm_bright" if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) elif output_type == 'return': return seg elif output_type == 'return_both': return (seg, mito_3d) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = NPM1_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_lamp1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_scaling_param = [3, 19] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 minArea = 15 ves_th_2d =0.1 vesselness_sigma = [1] vesselness_cutoff = 0.15 #hole_min = 60 hole_max = 1600 log_sigma_1 = 5 log_cutoff_1 = 0.09 log_sigma_2 = 2.5 log_cutoff_2 = 0.07 log_sigma_3 = 1 log_cutoff_3 = 0.01 ########################################################################## out_img_list = [] out_name_list = [] # intenisty normalization struct_img = intensity_normalization(struct_img, scaling_param=intensity_scaling_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') # spot detection response1 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_1) bw1 = response1> log_cutoff_1 response2 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_2) bw2 = response2> log_cutoff_2 bw_spot = np.logical_or(bw1, bw2) response3 = dot_slice_by_slice(structure_img_smooth, log_sigma=log_sigma_3) bw3 = response3> log_cutoff_3 bw_spot = np.logical_or(bw_spot, bw3) # ring/filament detection ves = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) bw_ves = ves> vesselness_cutoff # fill holes partial_fill = np.logical_or(bw_spot, bw_ves) out_img_list.append(partial_fill.copy()) out_name_list.append('interm_before_hole') holes = np.zeros_like(partial_fill) for zz in range(partial_fill.shape[0]): background_lab = label(~partial_fill[zz,:,:], connectivity=1) out = np.copy(background_lab) component_sizes = np.bincount(background_lab.ravel()) too_big = component_sizes >hole_max too_big_mask = too_big[background_lab] out[too_big_mask] = 0 #too_small = component_sizes <hole_min #too_small_mask = too_small[background_lab] #out[too_small_mask] = 0 holes[zz,:,:] = out full_fill = np.logical_or(partial_fill, holes) seg = remove_small_objects(full_fill, min_size=minArea, connectivity=1, in_place=False) # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = LAMP1_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_npm1_comb(struct_img, mitotic_stage, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [20, 25] gaussian_smoothing_sigma = 0.25 gaussian_smoothing_truncate_range = 4.0 dot_2d_sigma = 1 dot_2d_sigma_extra = 3 dot_2d_cutoff = 0.035 dot_2d_cutoff_extra = 0.01 minArea = 2 low_level_min_size = 700 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = np.reciprocal(struct_img) # inverting to detect dark spot struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed # if rescale_ratio>0: # struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") # struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) # gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: low level thresholding # global_median_1 = np.percentile(structure_img_smooth,35) global_median_2 = np.percentile(structure_img_smooth, 30) # 70 for M6M7, 30 for rest # th_low_level_1 = global_median_1 th_low_level_2 = global_median_2 # bw_low_level = (structure_img_smooth > th_low_level_1) + (structure_img_smooth > th_low_level_2) bw_low_level = structure_img_smooth > th_low_level_2 bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) seg = dilation(bw_low_level, selem=ball(2)) seg = np.invert(seg) seg = seg.astype(np.uint8) seg[seg > 0] = 255 #################### # POST-Processing using other segmentations structures #################### other_segs_path = "/allen/aics/assay-dev/computational/data/dna_cell_seg_on_production_data/NPM1/new_dna_mem_segmentation/" mem_segs_path = other_segs_path + fn + "_mem_segmentation.tiff" dna_segs_path = other_segs_path + fn + "_dna_segmentation.tiff" if not os.path.exists(mem_segs_path): mem_segs_path = other_segs_path + fn + ".ome_mem_segmentation.tiff" dna_segs_path = other_segs_path + fn + ".ome_dna_segmentation.tiff" mito_seed_path_root = "/allen/aics/assay-dev/computational/data/NPM1_segmentation_improvement/images_with_mitosis/M67/mito_seg/" mito_seed_path = mito_seed_path_root + fn + ".tiff" # Generate seed for mitotic cell if not os.path.exists(mito_seed_path): mito_seed_path = mito_seed_path_root + fn + ".ome.tiff" mito_seed_3d = imread(mito_seed_path) mito_seed_img = np.amax(mito_seed_3d, axis=0) mito_seed = com(mito_seed_img) # label the segmentations # mem_label, num_feat_mem = labeling(imread(mem_segs_path)) # not labeling correctly dna_label, num_feat_dna = labeling(imread(dna_segs_path)) # label # label_mito = mem_label[int(np.floor(mem_label.shape[0]/2)),int(mito_seed[0]),int(mito_seed[1])] # seg = seg * ((mem_label == label_mito)*1) seg[mito_seed_3d == 0] = 0 seg[dna_label > 0] = 0 out_img_list.append(seg.copy()) out_name_list.append('bw_fine') fn += "_combined" if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = NPM1_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_son( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure SON Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets ########################################################################## intensity_norm_param = [2, 30] vesselness_sigma = [1.2] vesselness_cutoff = 0.15 minArea = 15 # dot_2d_sigma = 1 dot_3d_sigma = 1.15 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # smoothing with boundary preserving smoothing structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### response_f3 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) response_f3 = response_f3 > vesselness_cutoff response_s3_1 = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) response_s3_3 = dot_3d(structure_img_smooth, log_sigma=3) bw_small_inverse = remove_small_objects(response_s3_1 > 0.03, min_size=150) bw_small = np.logical_xor(bw_small_inverse, response_s3_1 > 0.02) bw_medium = np.logical_or(bw_small, response_s3_1 > 0.07) bw_large = np.logical_or(response_s3_3 > 0.2, response_f3 > 0.25) bw = np.logical_or(np.logical_or(bw_small, bw_medium), bw_large) ################### # POST-PROCESSING ################### bw = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) for zz in range(bw.shape[0]): bw[zz, :, :] = remove_small_objects(bw[zz, :, :], min_size=3, connectivity=1, in_place=False) seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_slc25a17(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [2, 36] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_3d_sigma = 1 dot_3d_cutoff = 0.045 #0.03 #0.04 minArea = 3 #5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: LOG 3d response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) bw = response > dot_3d_cutoff bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) out_img_list.append(bw.copy()) out_name_list.append('interm_mask') # step 2: 'local_maxi + watershed' for cell cutting local_maxi = peak_local_max(struct_img,labels=label(bw), min_distance=2, indices=False) out_img_list.append(local_maxi.copy()) out_name_list.append('interm_local_max') distance = distance_transform_edt(bw) im_watershed = watershed(-1*distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True) ################### # POST-PROCESSING ################### seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) ###### HACK: Only for 2019 April Release ##### if np.count_nonzero(seg>0)<50000: print('FLAG: please check the meta data of the original CZI for QC') # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function #output_fun(out_img_list, out_name_list, output_path, fn) print('please provide custom output function') elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = SLC25A17_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_lmnb1_interphase(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[1, 0.01], [2, 0.01], [3, 0.01]] hole_max = 40000 hole_min = 400 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # get the mid frame mid_z = get_middle_frame(structure_img_smooth, method='intensity') # 2d filament filter on the middle frame bw_mid_z = filament_2d_wrapper(structure_img_smooth[mid_z, :, :], f2_param) # hole filling bw_fill_mid_z = hole_filling(bw_mid_z, hole_min, hole_max) seed = get_3dseed_from_mid_frame(np.logical_xor(bw_fill_mid_z, bw_mid_z), struct_img.shape, mid_z, hole_min, bg_seed=True) seg_filled = watershed( struct_img, seed.astype(int), watershed_line=True) > 1 # in watershed result, 1 is for background # get the actual shell seg = find_boundaries(seg_filled, connectivity=1, mode='thick') # output seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: print('your can implement your output hook here, but not yet') quit()
def ACTN1_HiPSC_Pipeline(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [3, 15] vesselness_sigma_1 = [2] vesselness_cutoff_1 = 0.15 vesselness_sigma_2 = [1] vesselness_cutoff_2 = 0.05 minArea = 5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) # smoothing structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # vesselness 3d response_1 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_1, tau=1, whiteonblack=True) response_2 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma_2, tau=1, whiteonblack=True) bw = np.logical_or(response_1 > vesselness_cutoff_1, response_2 > vesselness_cutoff_2) ################### # POST-PROCESSING ################### seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function # output_fun(out_img_list, out_name_list, output_path, fn) print('please provide custom output function') else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = ACTN1_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_fbl_labelfree_4dn( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure FBL Labelfree 4dn Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: minArea = 5 low_level_min_size = 7000 s2_param = [[0.5, 0.1]] intensity_scaling_param = [0.5, 19.5] gaussian_smoothing_sigma = 1 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization struct_norm = intensity_normalization( struct_img, scaling_param=intensity_scaling_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # smoothing struct_smooth = image_smoothing_gaussian_3d(struct_norm, sigma=gaussian_smoothing_sigma) out_img_list.append(struct_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # step 1: low level thresholding # global_otsu = threshold_otsu(structure_img_smooth) global_tri = threshold_triangle(struct_smooth) global_median = np.percentile(struct_smooth, 50) th_low_level = (global_tri + global_median) / 2 bw_low_level = struct_smooth > th_low_level bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) # step 2: high level thresholding bw_high_level = np.zeros_like(bw_low_level) lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) for idx in range(num_obj): single_obj = lab_low == (idx + 1) local_otsu = threshold_otsu(struct_smooth[single_obj]) bw_high_level[np.logical_and(struct_smooth > local_otsu * 1.2, single_obj)] = 1 # step 3: finer segmentation response2d = dot_2d_slice_by_slice_wrapper(struct_smooth, s2_param) bw_finer = remove_small_objects(response2d, min_size=minArea, connectivity=1, in_place=True) # merge finer level detection into high level coarse segmentation # to include outside dim parts bw_high_level[bw_finer > 0] = 1 ################### # POST-PROCESSING # make sure the variable name of final segmentation is 'seg' ################### seg = remove_small_objects(bw_high_level, min_size=minArea, connectivity=1, in_place=True) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions # TODO CREATE OUT_IMG_LIST/OUT_NAMELIST? output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_ctnnb1(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4, 27] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_2d_sigma = 1.5 dot_2d_cutoff = 0.01 minArea = 10 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### response = dot_slice_by_slice(structure_img_smooth, log_sigma=dot_2d_sigma) bw = response > dot_2d_cutoff ################### # POST-PROCESSING ################### seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = CTNNB1_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_son(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets ########################################################################## intensity_norm_param = [2, 30] vesselness_sigma = [1.2] vesselness_cutoff = 0.15 minArea = 15 dot_2d_sigma = 1 dot_3d_sigma = 1.15 ########################################################################## ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) # smoothing with boundary preserving smoothing structure_img_smooth = edge_preserving_smoothing_3d(struct_img) ################### # core algorithm ################### response_f3 = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) response_f3 = response_f3 > vesselness_cutoff response_s3_1 = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) response_s3_3 = dot_3d(structure_img_smooth, log_sigma=3) bw_small_inverse = remove_small_objects(response_s3_1>0.03, min_size=150) bw_small = np.logical_xor(bw_small_inverse, response_s3_1>0.02) bw_medium = np.logical_or(bw_small, response_s3_1>0.07) bw_large = np.logical_or(response_s3_3>0.2, response_f3>0.25) bw = np.logical_or( np.logical_or(bw_small, bw_medium), bw_large) ################### # POST-PROCESSING ################### bw = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) for zz in range(bw.shape[0]): bw[zz,: , :] = remove_small_objects(bw[zz,:,:], min_size=3, connectivity=1, in_place=False) seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: print('your can implement your output hook here, but not yet') quit()
def Workflow_slc25a17( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure SLC25A17 Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [2, 36] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_3d_sigma = 1 dot_3d_cutoff = 0.045 # 0.03 #0.04 minArea = 3 # 5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # rescale if needed if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = ( gaussian_smoothing_truncate_range * rescale_ratio) # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_slice_by_slice( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range, ) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # step 1: LOG 3d response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) bw = response > dot_3d_cutoff bw = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) out_img_list.append(bw.copy()) out_name_list.append("interm_mask") # step 2: 'local_maxi + watershed' for cell cutting local_maxi = peak_local_max(struct_img, labels=label(bw), min_distance=2, indices=False) out_img_list.append(local_maxi.copy()) out_name_list.append("interm_local_max") distance = distance_transform_edt(bw) im_watershed = watershed( -1 * distance, label(dilation(local_maxi, selem=ball(1))), mask=bw, watershed_line=True, ) ################### # POST-PROCESSING ################### seg = remove_small_objects(im_watershed, min_size=minArea, connectivity=1, in_place=False) # HACK: Only for 2019 April Release ##### if np.count_nonzero(seg > 0) < 50000: print("FLAG: please check the meta data of the original CZI for QC") # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_lmnb1_mitotic(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [4000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 f2_param = [[0.5, 0.01]] minArea = 5 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with boundary preserving smoothing structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # 2d filament filter on the middle frame bw = filament_2d_wrapper(structure_img_smooth, f2_param) ################### # POST-PROCESSING ################### bw = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = bw > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: print('your can implement your output hook here, but not yet') quit()
def ST6GAL1_HiPSC_Pipeline(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [9, 19] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 cell_wise_min_area = 1200 dot_3d_sigma = 1.6 dot_3d_cutoff = 0.02 minArea = 10 thin_dist = 1 thin_dist_preserve = 1.6 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_3d( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # cell-wise local adaptive thresholding th_low_level = threshold_triangle(structure_img_smooth) bw_low_level = structure_img_smooth > th_low_level bw_low_level = remove_small_objects(bw_low_level, min_size=cell_wise_min_area, connectivity=1, in_place=True) bw_low_level = dilation(bw_low_level, selem=ball(2)) bw_high_level = np.zeros_like(bw_low_level) lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) for idx in range(num_obj): single_obj = lab_low == (idx + 1) local_otsu = threshold_otsu(structure_img_smooth[single_obj > 0]) bw_high_level[np.logical_and(structure_img_smooth > local_otsu * 0.98, single_obj)] = 1 # LOG 3d to capture spots response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) bw_extra = response > dot_3d_cutoff # thinning bw_high_level = topology_preserving_thinning(bw_high_level, thin_dist_preserve, thin_dist) # combine the two parts bw = np.logical_or(bw_high_level, bw_extra) ################### # POST-PROCESSING ################### seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for other pre-defined RnD output functions (AICS internal) ST6GAL1_output(out_img_list, out_name_list, output_type, output_path, fn)
def RAB5A_HiPSC_Pipeline(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [1000] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 dot_3d_sigma = 1 dot_3d_cutoff = 0.03 hole_min = 0 hole_max = 81 minArea = 3 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_slice_by_slice( struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: LOG 3d response = dot_3d(structure_img_smooth, log_sigma=dot_3d_sigma) bw = response > dot_3d_cutoff # step 2: fill holes and remove small objects bw_filled = hole_filling(bw, hole_min, hole_max, True) seg = remove_small_objects(bw_filled, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = RAB5A_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_nup153(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [1, 13.5] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 s3_param = [[1, 0.07]] #s2_param = [[1, 0.04]] minArea = 7 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with edge_preserving_smoothing filter structure_img_smooth = edge_preserving_smoothing_3d(struct_img) #structure_img_smooth = image_smoothing_gaussian_slice_by_slice(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # step 1: LOG 3d bw = dot_3d_wrapper(structure_img_smooth, s3_param) #bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param) ################### # POST-PROCESSING ################### seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint16) seg[seg > 0] = 65535 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: pass
def Workflow_tomm20(struct_img,rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [3.5, 15] gaussian_smoothing_sigma = 1 gaussian_smoothing_truncate_range = 3.0 vesselness_sigma = [1.5] vesselness_cutoff = 0.16 minArea = 10 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio>0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8)/(struct_img.max() - struct_img.min() + 1e-8) gaussian_smoothing_truncate_range = gaussian_smoothing_truncate_range * rescale_ratio # smoothing with gaussian filter structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma, truncate_range=gaussian_smoothing_truncate_range) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # 2d vesselness slice by slice response = vesselnessSliceBySlice(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) bw = response > vesselness_cutoff ################### # POST-PROCESSING ################### seg = remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg>0 seg = seg.astype(np.uint8) seg[seg>0]=255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = TOMM20_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def TEMPLATE_HiPSC_Pipeline(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets # ADD you parameters here intensity_norm_param = [] minArea = 0 #ADD-HERE ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with gaussian filter structure_img_smooth = ADD_SMOOTHING_FUNCTION_HERE #ADD-HERE out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### bw = ADD_CORE_ALGORITHMS_HERE #ADD-HERE ################### # POST-PROCESSING ################### seg = remove_small_objects(bw, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data (allen institute internal) save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for other pre-defined RnD output functions (AICS internal) DSP_output(out_img_list, out_name_list, output_type, output_path, fn)
def Workflow_cardio_ttn(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [8, 15.5] vesselness_sigma = [1] vesselness_cutoff = 0.02 minArea = 15 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = processing.resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with gaussian filter structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### # vesselness 3d response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) bw = response > vesselness_cutoff ################### # POST-PROCESSING ################### seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) else: # the hook for other pre-defined RnD output functions (AICS internal) TTN_Cardio_output(out_img_list, out_name_list, output_type, output_path, fn)
def Workflow_smc1a(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [2.5, 12] s2_param = [[1, 0.06]] minArea = 3 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append('im_norm') # rescale if needed if rescale_ratio > 0: struct_img = resize(struct_img, [1, rescale_ratio, rescale_ratio], method="cubic") struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with gaussian filter structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append('im_smooth') ################### # core algorithm ################### bw = dot_2d_slice_by_slice_wrapper(structure_img_smooth, s2_param) ################### # POST-PROCESSING ################### seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append('bw_final') if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'AICS_pipeline': # pre-defined output function for pipeline data save_segmentation(seg, True, output_path, fn) elif output_type == 'customize': # the hook for passing in a customized output function output_fun(out_img_list, out_name_list, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: # the hook for pre-defined RnD output functions (AICS internal) img_list, name_list = FBL_output(out_img_list, out_name_list, output_type, output_path, fn) if output_type == 'QCB': return img_list, name_list
def Workflow_cardio_myl7( struct_img: np.ndarray, rescale_ratio: float = -1, output_type: str = "default", output_path: Union[str, Path] = None, fn: Union[str, Path] = None, output_func=None, ): """ classic segmentation workflow wrapper for structure Cardio MYL7 Parameter: ----------- struct_img: np.ndarray the 3D image to be segmented rescale_ratio: float an optional parameter to allow rescale the image before running the segmentation functions, default is no rescaling output_type: str select how to handle output. Currently, four types are supported: 1. default: the result will be saved at output_path whose filename is original name without extention + "_struct_segmentaiton.tiff" 2. array: the segmentation result will be simply returned as a numpy array 3. array_with_contour: segmentation result will be returned together with the contour of the segmentation 4. customize: pass in an extra output_func to do a special save. All the intermediate results, names of these results, the output_path, and the original filename (without extension) will be passed in to output_func. """ ########################################################################## # PARAMETERS: # note that these parameters are supposed to be fixed for the structure # and work well accross different datasets intensity_norm_param = [8, 15.5] vesselness_sigma = [1] vesselness_cutoff = 0.01 minArea = 15 ########################################################################## out_img_list = [] out_name_list = [] ################### # PRE_PROCESSING ################### # intenisty normalization (min/max) struct_img = intensity_normalization(struct_img, scaling_param=intensity_norm_param) out_img_list.append(struct_img.copy()) out_name_list.append("im_norm") # rescale if needed if rescale_ratio > 0: struct_img = zoom(struct_img, (1, rescale_ratio, rescale_ratio), order=2) struct_img = (struct_img - struct_img.min() + 1e-8) / (struct_img.max() - struct_img.min() + 1e-8) # smoothing with gaussian filter structure_img_smooth = edge_preserving_smoothing_3d(struct_img) out_img_list.append(structure_img_smooth.copy()) out_name_list.append("im_smooth") ################### # core algorithm ################### # vesselness 3d response = vesselness3D(structure_img_smooth, sigmas=vesselness_sigma, tau=1, whiteonblack=True) bw = response > vesselness_cutoff ################### # POST-PROCESSING ################### seg = remove_small_objects(bw > 0, min_size=minArea, connectivity=1, in_place=False) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 out_img_list.append(seg.copy()) out_name_list.append("bw_final") if output_type == "default": # the default final output, simply save it to the output path save_segmentation(seg, False, Path(output_path), fn) elif output_type == "customize": # the hook for passing in a customized output function # use "out_img_list" and "out_name_list" in your hook to # customize your output functions output_func(out_img_list, out_name_list, Path(output_path), fn) elif output_type == "array": return seg elif output_type == "array_with_contour": return (seg, generate_segmentation_contour(seg)) else: raise NotImplementedError("invalid output type: {output_type}")
def Workflow_npm_labelfree_4dn(struct_img, rescale_ratio, output_type, output_path, fn, output_func=None): ########################################################################## # PARAMETERS: minArea = 5 low_level_min_size = 7000 s2_param = [[0.5, 0.12]] intensity_scaling_param = [2, 16.5] gaussian_smoothing_sigma = 1 ########################################################################## ################### # PRE_PROCESSING ################### # intenisty normalization struct_norm = intensity_normalization( struct_img, scaling_param=intensity_scaling_param) # smoothing struct_smooth = image_smoothing_gaussian_3d(struct_norm, sigma=gaussian_smoothing_sigma) ################### # core algorithm ################### # step 1: low level thresholding #global_otsu = threshold_otsu(structure_img_smooth) global_tri = threshold_triangle(struct_smooth) global_median = np.percentile(struct_smooth, 50) th_low_level = (global_tri + global_median) / 2 bw_low_level = struct_smooth > th_low_level bw_low_level = remove_small_objects(bw_low_level, min_size=low_level_min_size, connectivity=1, in_place=True) # step 2: high level thresholding bw_high_level = np.zeros_like(bw_low_level) lab_low, num_obj = label(bw_low_level, return_num=True, connectivity=1) for idx in range(num_obj): single_obj = (lab_low == (idx + 1)) local_otsu = threshold_otsu(struct_smooth[single_obj]) bw_high_level[np.logical_and(struct_smooth > local_otsu * 1.2, single_obj)] = 1 # step 3: finer segmentation response2d = dot_2d_slice_by_slice_wrapper(struct_smooth, s2_param) bw_finer = remove_small_objects(response2d, min_size=minArea, connectivity=1, in_place=True) # merge finer level detection into high level coarse segmentation to include outside dim parts bw_high_level[bw_finer > 0] = 1 ################### # POST-PROCESSING # make sure the variable name of final segmentation is 'seg' ################### seg = remove_small_objects(bw_high_level, min_size=minArea, connectivity=1, in_place=True) # output seg = seg > 0 seg = seg.astype(np.uint8) seg[seg > 0] = 255 if output_type == 'default': # the default final output save_segmentation(seg, False, output_path, fn) elif output_type == 'array': return seg elif output_type == 'array_with_contour': return (seg, generate_segmentation_contour(seg)) else: print('your can implement your output hook here, but not yet') quit()