Source code for ark.segmentation.regionprops_extraction


import numpy as np
import pandas as pd
from skimage.measure import label, moments, regionprops_table


[docs]def major_minor_axis_ratio(prop, **kwargs): """Return the ratio of the major axis length to the minor axis length Args: prop (skimage.measure.regionprops): The property information for a cell returned by regionprops **kwargs: Arbitrary keyword arguments Returns: float: major axis length / minor axis length """ if prop.minor_axis_length == 0: return np.float('NaN') else: return prop.major_axis_length / prop.minor_axis_length
[docs]def perim_square_over_area(prop, **kwargs): """Return the ratio of the squared perimeter to the cell area Args: prop (skimage.measure.regionprops): The property information for a cell returned by regionprops **kwargs: Arbitrary keyword arguments Returns: float: perimeter^2 / area """ return np.square(prop.perimeter) / prop.area
[docs]def major_axis_equiv_diam_ratio(prop, **kwargs): """Return the ratio of the major axis length to the equivalent diameter Args: prop (skimage.measure.regionprops): The property information for a cell returned by regionprops **kwargs: Arbitrary keyword arguments Returns: float: major axis length / equivalent diameter """ return prop.major_axis_length / prop.equivalent_diameter
[docs]def convex_hull_resid(prop, **kwargs): """Return the ratio of the difference between convex area and area to convex area Args: prop (skimage.measure.regionprops): The property information for a cell returned by regionprops **kwargs: Arbitrary keyword arguments Returns: float: (convex area - area) / convex area """ return (prop.convex_area - prop.area) / prop.convex_area
[docs]def centroid_dif(prop, **kwargs): """Return the normalized euclidian distance between the centroid of the cell and the centroid of the corresponding convex hull Args: prop (skimage.measure.regionprops): The property information for a cell returned by regionprops **kwargs: Arbitrary keyword arguments Returns: float: The centroid shift for the cell """ cell_image = prop.image cell_M = moments(cell_image) cell_centroid = np.array([cell_M[1, 0] / cell_M[0, 0], cell_M[0, 1] / cell_M[0, 0]]) convex_image = prop.convex_image convex_M = moments(convex_image) convex_centroid = np.array([convex_M[1, 0] / convex_M[0, 0], convex_M[0, 1] / convex_M[0, 0]]) centroid_dist = np.linalg.norm(cell_centroid - convex_centroid) / np.sqrt(prop.area) return centroid_dist
[docs]def num_concavities(prop, **kwargs): """Return the number of concavities for a cell Args: prop (skimage.measure.regionprops): The property information for a cell returned by regionprops **kwargs: Arbitrary keyword arguments Returns: int: The number of concavities for a cell """ cell_image = prop.image convex_image = prop.convex_image diff_img = convex_image ^ cell_image if np.sum(diff_img) > 0: labeled_diff_img = label(diff_img, connectivity=1) hull_prop_df = pd.DataFrame(regionprops_table(labeled_diff_img, properties=['area', 'perimeter'])) hull_prop_df['compactness'] = np.square(hull_prop_df['perimeter']) / hull_prop_df['area'] small_idx_area_cutoff = kwargs.get('small_concavity_minimum', 10) compactness_cutoff = kwargs.get('max_compactness', 60) large_idx_area_cutoff = kwargs.get('large_concavity_minimum', 150) small_idx = np.logical_and(hull_prop_df['area'] > small_idx_area_cutoff, hull_prop_df['compactness'] < compactness_cutoff) large_idx = hull_prop_df['area'] > large_idx_area_cutoff combined_idx = np.logical_or(small_idx, large_idx) concavities = np.sum(combined_idx) else: concavities = 0 return concavities
[docs]def nc_ratio(marker_counts, **kwargs): """Return the ratio of the nuclear area to total cell area Args: marker_counts (xarray.DataArray): xarray containing segmentaed data of cells x markers **kwargs: Arbitrary keyword arguments """ # get the whole cell and nuclear area information whole_cell_areas = marker_counts.loc['whole_cell', :, 'area'] nuclear_areas = marker_counts.loc['nuclear', :, 'area'] # compute nc_ratio by dividing nuclear by whole cell area, set infs to 0 marker_counts.loc['nuclear', :, 'nc_ratio'] = np.nan_to_num(nuclear_areas / whole_cell_areas, posinf=0, neginf=0) # copy nc_ratio to whole_cell because it applies to both dimensions marker_counts.loc['whole_cell', :, 'nc_ratio'] = marker_counts.loc['nuclear', :, 'nc_ratio'] return marker_counts
REGIONPROPS_FUNCTION = { 'major_minor_axis_ratio': major_minor_axis_ratio, 'perim_square_over_area': perim_square_over_area, 'major_axis_equiv_diam_ratio': major_axis_equiv_diam_ratio, 'convex_hull_resid': convex_hull_resid, 'centroid_dif': centroid_dif, 'num_concavities': num_concavities, 'nc_ratio': nc_ratio }