def segment_images(inpDir, outDir, config_data): 
    """ Workflow for data with similar morphology
    as sialyltransferase 1.

    Args:
        inpDir : path to the input directory
        outDir : path to the output directory
        config_data : path to the configuration file
    """

    logging.basicConfig(format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s',
                        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("main")
    logger.setLevel(logging.INFO)

    inpDir_files = os.listdir(inpDir)
    for i,f in enumerate(inpDir_files):
        logger.info('Segmenting image : {}'.format(f))
        
        # Load image
        br = BioReader(os.path.join(inpDir,f))
        image = br.read_image()
        structure_channel = 0 
        struct_img0 = image[:,:,:,structure_channel,0]
        struct_img0 = struct_img0.transpose(2,0,1).astype(np.float32)

        # main algorithm
        intensity_scaling_param = config_data['intensity_scaling_param']
        struct_img = intensity_normalization(struct_img0, scaling_param=intensity_scaling_param) 
        gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma'] 
        structure_img_smooth = image_smoothing_gaussian_3d(struct_img, sigma=gaussian_smoothing_sigma)
        global_thresh_method = config_data['global_thresh_method'] 
        object_minArea = config_data['object_minArea'] 
        bw, object_for_debug = MO(structure_img_smooth, global_thresh_method=global_thresh_method, object_minArea=object_minArea, return_object=True)
        thin_dist_preserve = config_data['thin_dist_preserve']
        thin_dist = config_data['thin_dist']
        bw_thin = topology_preserving_thinning(bw>0, thin_dist_preserve, thin_dist)
        s3_param = config_data['s3_param']
        bw_extra = dot_3d_wrapper(structure_img_smooth, s3_param)
        bw_combine = np.logical_or(bw_extra>0, bw_thin)
        minArea = config_data['minArea']
        seg = remove_small_objects(bw_combine>0, min_size=minArea, connectivity=1, in_place=False)
        seg = seg > 0
        out_img=seg.astype(np.uint8)
        out_img[out_img>0]=255
    
        # create output image
        out_img = out_img.transpose(1,2,0)
        out_img = out_img.reshape((out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1))

        # write image using BFIO
        bw = BioWriter(os.path.join(outDir,f), metadata=br.read_metadata())
        bw.num_x(out_img.shape[1])
        bw.num_y(out_img.shape[0])
        bw.num_z(out_img.shape[2])
        bw.num_c(out_img.shape[3])
        bw.num_t(out_img.shape[4])
        bw.pixel_type(dtype='uint8')
        bw.write_image(out_img)
        bw.close_image()
Beispiel #2
0
def segment_images(inpDir, outDir, config_data):
    """ Workflow for data with similar morphology
    as connexin-43

    Args:
        inpDir : path to the input directory
        outDir : path to the output directory
        config_data : path to the configuration file
    """

    logging.basicConfig(
        format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s',
        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("main")
    logger.setLevel(logging.INFO)

    inpDir_files = os.listdir(inpDir)
    for i, f in enumerate(inpDir_files):
        logger.info('Segmenting image : {}'.format(f))

        # Load image
        br = BioReader(os.path.join(inpDir, f))
        image = br.read_image()
        structure_channel = 0
        struct_img0 = image[:, :, :, structure_channel, 0]
        struct_img0 = struct_img0.transpose(2, 0, 1).astype(np.float32)

        # main algorithm
        intensity_scaling_param = config_data['intensity_scaling_param']
        struct_img = intensity_normalization(
            struct_img0, scaling_param=intensity_scaling_param)
        gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma']
        structure_img_smooth = image_smoothing_gaussian_slice_by_slice(
            struct_img, sigma=gaussian_smoothing_sigma)
        s3_param = config_data['s3_param']
        bw = dot_3d_wrapper(structure_img_smooth, s3_param)
        minArea = config_data['minArea']
        seg = remove_small_objects(bw > 0,
                                   min_size=minArea,
                                   connectivity=1,
                                   in_place=False)
        seg = seg > 0
        out_img = seg.astype(np.uint8)
        out_img[out_img > 0] = 255

        # create output image
        out_img = out_img.transpose(1, 2, 0)
        out_img = out_img.reshape(
            (out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1))

        # write image using BFIO
        bw = BioWriter(os.path.join(outDir, f))
        bw.num_x(out_img.shape[1])
        bw.num_y(out_img.shape[0])
        bw.num_z(out_img.shape[2])
        bw.num_c(out_img.shape[3])
        bw.num_t(out_img.shape[4])
        bw.pixel_type(dtype='uint8')
        bw.write_image(out_img)
        bw.close_image()
Beispiel #3
0
def pex_seg(image, img_seg):
    slices = []
    Vol = []
    pex_seg_img = []
    pex_seg_n = []
    slices = ndi.find_objects(img_seg)
    img = intensity_normalization(image, scale)
    img = image_smoothing_gaussian_3d(img, sigma)
    for i, c in enumerate(slices):
        cell_V = img_seg[c]
        vt, f, n, val = marching_cubes_lewiner(cell_V)
        Tvol = 1 / 6 * det(vt[f])
        vol = abs(sum(Tvol))
        Vol.append(vol)
        cell = image[c]
        cell_s = img[c]
        bw = dot_3d_wrapper(cell_s, s3)
        mask = remove_small_objects(bw > 0,
                                    min_size=2,
                                    connectivity=1,
                                    in_place=False)
        seed = dilation(peak_local_max(cell,
                                       labels=label(mask),
                                       min_distance=2,
                                       indices=False),
                        selem=ball(1))
        ws_map = -1 * ndi.distance_transform_edt(bw)
        seg = watershed(ws_map, label(seed), mask=mask, watershed_line=True)
        regions = regionprops(seg)
        n = len(regions)
        n = max(0, n)
        pex_seg_img.append(seg)
        pex_seg_n.append(n)
    df = pd.DataFrame({
        "Slices": slices,
        "Cell Vol": Vol,
        "Pex count": pex_seg_n
    })
    return df, pex_seg_img
Beispiel #4
0
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_drug_npm1(
    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 drug treated NPM1

    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
    """
    ##########################################################################
    # 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 = 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
    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
    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, 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}")
dims = {}
for dimension in dim_iter:
    dim_id = dimension.get('Id')
    dims.update({dim_id:float(dimension.find('Value').text)*1.E6}) # [um]
voxel_vol = dims['X'] * dims['Y'] * dims['Z']  # [um^3]
dims_xyz = np.array([dims['X'], dims['Y'], dims['Z']])


#--  SEGMENT SPOTS  -----------------------------------------------------------#
for i, g in enumerate(genes):
    print('\nProcessing gene ' + g + '...\n')
    print('Smoothing image...')
    img_rna_smooth = image_smoothing_gaussian_3d(imgs_rna[i], sigma=1)
    s3_param = [[1, 0.75*t_spots[i]], [2, 0.75*t_spots[i]]]
    print('Identifying spots...')
    bw = dot_3d_wrapper(img_rna_smooth, s3_param)

    # watershed
    minArea = 4
    Mask = morphology.remove_small_objects(bw>0, min_size=minArea, connectivity=1, in_place=False) 
    labeled_mask = measure.label(Mask)
    
    print('Performing watershed segmentation...')
    peaks = feature.peak_local_max(imgs_rna[i],labels=labeled_mask, min_distance=2, indices=False)
    Seed = morphology.binary_dilation(peaks, selem=morphology.ball(1))
    Watershed_Map = -1*distance_transform_edt(bw)
    seg = morphology.watershed(Watershed_Map, measure.label(Seed), mask=Mask, watershed_line=True)
    seg = morphology.remove_small_objects(seg>0, min_size=minArea, connectivity=1, in_place=False)

    print('Exporting mask...')
    outname = img_name + '_mask^' + g + '.tiff'
Beispiel #7
0
def segment_images(inpDir, outDir, config_data):
    """ Workflow for dot like shapes such as
    Centrin-2, Desmoplakin, PMP34. 

    Args:
        inpDir : path to the input directory
        outDir : path to the output directory
        config_data : path to the configuration file
    """

    logging.basicConfig(
        format='%(asctime)s - %(name)-8s - %(levelname)-8s - %(message)s',
        datefmt='%d-%b-%y %H:%M:%S')
    logger = logging.getLogger("main")
    logger.setLevel(logging.INFO)

    inpDir_files = os.listdir(inpDir)
    for i, f in enumerate(inpDir_files):
        logger.info('Segmenting image : {}'.format(f))

        # Load an image
        br = BioReader(os.path.join(inpDir, f))
        image = br.read_image()
        structure_channel = 0
        struct_img0 = image[:, :, :, structure_channel, 0]
        struct_img0 = struct_img0.transpose(2, 0, 1).astype(np.float32)

        # main algorithm
        intensity_scaling_param = config_data['intensity_scaling_param']
        struct_img = intensity_normalization(
            struct_img0, scaling_param=intensity_scaling_param)

        gaussian_smoothing_sigma = config_data['gaussian_smoothing_sigma']
        if config_data["gaussian_smoothing"] == "gaussian_slice_by_slice":
            structure_img_smooth = image_smoothing_gaussian_slice_by_slice(
                struct_img, sigma=gaussian_smoothing_sigma)
        else:
            structure_img_smooth = image_smoothing_gaussian_3d(
                struct_img, sigma=gaussian_smoothing_sigma)
        s3_param = config_data['s3_param']
        bw = dot_3d_wrapper(structure_img_smooth, s3_param)
        minArea = config_data['minArea']
        Mask = remove_small_objects(bw > 0,
                                    min_size=minArea,
                                    connectivity=1,
                                    in_place=False)
        Seed = dilation(peak_local_max(struct_img,
                                       labels=label(Mask),
                                       min_distance=2,
                                       indices=False),
                        selem=ball(1))
        Watershed_Map = -1 * distance_transform_edt(bw)
        seg = watershed(Watershed_Map,
                        label(Seed),
                        mask=Mask,
                        watershed_line=True)
        seg = remove_small_objects(seg > 0,
                                   min_size=minArea,
                                   connectivity=1,
                                   in_place=False)
        seg = seg > 0
        out_img = seg.astype(np.uint8)
        out_img[out_img > 0] = 255

        # create output image
        out_img = out_img.transpose(1, 2, 0)
        out_img = out_img.reshape(
            (out_img.shape[0], out_img.shape[1], out_img.shape[2], 1, 1))

        # write image using BFIO
        bw = BioWriter(os.path.join(outDir, f))
        bw.num_x(out_img.shape[1])
        bw.num_y(out_img.shape[0])
        bw.num_z(out_img.shape[2])
        bw.num_c(out_img.shape[3])
        bw.num_t(out_img.shape[4])
        bw.pixel_type(dtype='uint8')
        bw.write_image(out_img)
        bw.close_image()
def Workflow_nup153(
    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 NUP153

    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 = [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 = 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 edge_preserving_smoothing 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
    ###################

    # 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, 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}")