def build_distance_layers(cyt_coord, nuc_coord, rna_coord, normalized=True): """Compute distance layers as input for the model. Parameters ---------- cyt_coord : np.ndarray, np.int64 Array of cytoplasm boundaries coordinates with shape (nb_points, 2). nuc_coord : np.ndarray, np.int64 Array of nucleus boundaries coordinates with shape (nb_points, 2). rna_coord : np.ndarray, np.int64 Array of mRNAs coordinates with shape (nb_points, 2) or (nb_points, 3). normalized : bool Normalized the layers between 0 and 1. Returns ------- distance_cyt : np.ndarray, np.float32 A 2-d tensor with shape (y, x) showing distance to the cytoplasm border. Normalize between 0 and 1 if 'normalized' True. distance_nuc : np.ndarray, np.float32 A 2-d tensor with shape (y, x) showing distance to the nucleus border. Normalize between 0 and 1 if 'normalized' True. """ # check parameters stack.check_array(cyt_coord, ndim=2, dtype=[np.int64]) if nuc_coord is not None: stack.check_array(nuc_coord, ndim=2, dtype=[np.int64]) if rna_coord is not None: stack.check_array(rna_coord, ndim=2, dtype=[np.int64]) stack.check_parameter(normalized=bool) # build surface binary matrices from coordinates cyt_surface, nuc_surface, rna_layer, _ = stack.from_coord_to_surface( cyt_coord=cyt_coord, nuc_coord=nuc_coord, rna_coord=rna_coord) # compute distances map for cytoplasm and nucleus cyt_distance = ndi.distance_transform_edt(cyt_surface) nuc_distance_ = ndi.distance_transform_edt(~nuc_surface) nuc_distance = cyt_surface * nuc_distance_ if normalized: # cast to np.float32 and normalize it between 0 and 1 cyt_distance = cyt_distance / cyt_distance.max() nuc_distance = nuc_distance / nuc_distance.max() # cast layer in float32 cyt_distance = stack.cast_img_float32(cyt_distance) nuc_distance = stack.cast_img_float32(nuc_distance) rna_layer = stack.cast_img_float32(rna_layer) return cyt_distance, nuc_distance, rna_layer
def test_log_filter(): # float64 y_float64 = stack.cast_img_float64(y) filtered_y_float64 = stack.log_filter(y_float64, 2) expected_y_float64 = np.array( [[0., 0., 0.02995949, 0.06212277, 0.07584532], [0., 0., 0.02581818, 0.05134284, 0.06123539], [0., 0., 0.01196859, 0.0253716, 0.02853162], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.]], dtype=np.float64) assert_allclose(filtered_y_float64, expected_y_float64, rtol=1e-6) assert filtered_y_float64.dtype == np.float64 # float32 y_float32 = stack.cast_img_float32(y) filtered_y = stack.log_filter(y_float32, 2) expected_y = stack.cast_img_float32(expected_y_float64) assert_allclose(filtered_y, expected_y, rtol=1e-6) assert filtered_y.dtype == np.float32 # uint8 filtered_y = stack.log_filter(y, 2) expected_y = stack.cast_img_uint8(expected_y_float64) assert_array_equal(filtered_y, expected_y) assert filtered_y.dtype == np.uint8 # uint16 y_uint16 = stack.cast_img_uint16(y) filtered_y = stack.log_filter(y_uint16, 2) expected_y = stack.cast_img_uint16(expected_y_float64) assert_array_equal(filtered_y, expected_y) assert filtered_y.dtype == np.uint16
def build_boundaries_layers(cyt_coord, nuc_coord, rna_coord): """ Parameters ---------- cyt_coord : np.ndarray, np.int64 Array of cytoplasm boundaries coordinates with shape (nb_points, 2). nuc_coord : np.ndarray, np.int64 Array of nucleus boundaries coordinates with shape (nb_points, 2). rna_coord : np.ndarray, np.int64 Array of mRNAs coordinates with shape (nb_points, 2) or (nb_points, 3). Returns ------- cyt_boundaries : np.ndarray, np.float32 A 2-d binary tensor with shape (y, x) showing cytoplasm boundaries. border. nuc_boundaries : np.ndarray, np.float32 A 2-d binary tensor with shape (y, x) showing nucleus boundaries. rna_layer : np.ndarray, np.float32 Binary image of mRNAs localizations with shape (y, x). """ # check parameters stack.check_array(cyt_coord, ndim=2, dtype=[np.int64]) if nuc_coord is not None: stack.check_array(nuc_coord, ndim=2, dtype=[np.int64]) if rna_coord is not None: stack.check_array(rna_coord, ndim=2, dtype=[np.int64]) # build surface binary matrices from coordinates cyt_surface, nuc_surface, rna_layer, _ = stack.from_coord_to_surface( cyt_coord=cyt_coord, nuc_coord=nuc_coord, rna_coord=rna_coord) # from surface binary matrices to boundaries binary matrices cyt_boundaries = stack.from_surface_to_boundaries(cyt_surface) nuc_boundaries = stack.from_surface_to_boundaries(nuc_surface) # cast layer in float32 cyt_boundaries = stack.cast_img_float32(cyt_boundaries) nuc_boundaries = stack.cast_img_float32(nuc_boundaries) rna_layer = stack.cast_img_float32(rna_layer) return cyt_boundaries, nuc_boundaries, rna_layer
def prepare_coordinate_data(cyt_coord, nuc_coord, rna_coord): # get a binary representation of the coordinates cyt, nuc = from_coord_to_matrix(cyt_coord, nuc_coord) rna_coord[:, 1:3] += stack.get_offset_value() # fill in masks mask_cyt, mask_nuc = stack.get_surface_layers(cyt, nuc, cast_float=False) # get mask cytoplasm outside nucleus mask_cyt_out = mask_cyt.copy() mask_cyt_out[mask_nuc] = False # compute distance maps for the cytoplasm and the nucleus distance_cyt, distance_nuc = stack.get_distance_layers(cyt, nuc, normalized=False) # normalize distance maps between 0 and 1 distance_cyt_normalized = distance_cyt / distance_cyt.max() distance_cyt_normalized = stack.cast_img_float32(distance_cyt_normalized) distance_nuc_normalized = distance_nuc / distance_nuc.max() distance_nuc_normalized = stack.cast_img_float32(distance_nuc_normalized) # get rna outside nucleus mask_rna_in = mask_nuc[rna_coord[:, 1], rna_coord[:, 2]] rna_coord_out = rna_coord[~mask_rna_in] # get centroids centroid_cyt = get_centroid_surface(mask_cyt) centroid_nuc = get_centroid_surface(mask_nuc) centroid_rna = get_centroid_rna(rna_coord) if len(rna_coord_out) == 0: centroid_rna_out = centroid_cyt.copy() else: centroid_rna_out = get_centroid_rna(rna_coord_out) # get centroid distance maps distance_cyt_centroid = get_centroid_distance_map(centroid_cyt, mask_cyt) distance_nuc_centroid = get_centroid_distance_map(centroid_nuc, mask_cyt) distance_rna_out_centroid = get_centroid_distance_map( centroid_rna_out, mask_cyt) prepared_inputs = (mask_cyt, mask_nuc, mask_cyt_out, distance_cyt, distance_nuc, distance_cyt_normalized, distance_nuc_normalized, rna_coord_out, centroid_cyt, centroid_nuc, centroid_rna, centroid_rna_out, distance_cyt_centroid, distance_nuc_centroid, distance_rna_out_centroid) return prepared_inputs
def test_cast_float32(dtype): # from integer to np.float32 if np.issubdtype(dtype, np.integer): x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] tensor = np.array(x).reshape((3, 3)).astype(dtype) tensor[0, 0] = np.iinfo(dtype).min tensor[2, 2] = np.iinfo(dtype).max # from float to np.float32 else: x = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 1.0]] tensor = np.array(x).reshape((3, 3)).astype(dtype) # cast in float32 tensor_float32 = stack.cast_img_float32(tensor) assert tensor_float32.dtype == np.float32 # check value if dtype in [np.uint8, np.uint16, np.uint32, np.uint64]: assert tensor_float32.min() == 0 assert tensor_float32.max() == 1 elif dtype in [np.int8, np.int16, np.int32, np.int64]: assert tensor_float32.min() == -1 assert tensor_float32.max() == 1 else: assert_array_almost_equal(tensor_float32, tensor)
def test_cast_float32(dtype): # from integer to np.float32 if np.issubdtype(dtype, np.integer): x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] tensor = np.array(x).reshape((3, 3)).astype(dtype) tensor[2, 2] = np.iinfo(dtype).max # from float to np.float32 else: x = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 1.0]] tensor = np.array(x).reshape((3, 3)).astype(dtype) # cast in float32 if dtype == np.float64: with pytest.warns(UserWarning): tensor_float32 = stack.cast_img_float32(tensor) else: tensor_float32 = stack.cast_img_float32(tensor) assert tensor_float32.dtype == np.float32
def test_gaussian_filter(): # float64 y_float64 = stack.cast_img_float64(y) filtered_y_float64 = stack.gaussian_filter(y_float64, 2) expected_y_float64 = np.array( [[0.08928096, 0.1573019, 0.22897881, 0.28086597, 0.3001061], [0.08668051, 0.14896399, 0.21282558, 0.25752308, 0.27253406], [0.07634613, 0.12664142, 0.17574502, 0.20765944, 0.2155001], [0.05890843, 0.09356377, 0.12493327, 0.1427122, 0.14374558], [0.03878372, 0.05873308, 0.07492625, 0.08201409, 0.07939603]], dtype=np.float64) assert_allclose(filtered_y_float64, expected_y_float64, rtol=1e-6) assert filtered_y_float64.dtype == np.float64 # float32 y_float32 = stack.cast_img_float32(y) filtered_y = stack.gaussian_filter(y_float32, 2) expected_y = stack.cast_img_float32(expected_y_float64) assert_allclose(filtered_y, expected_y, rtol=1e-6) assert filtered_y.dtype == np.float32 # uint8 with pytest.raises(ValueError): stack.gaussian_filter(y, 2, allow_negative=True) filtered_y = stack.gaussian_filter(y, 2) expected_y = stack.cast_img_uint8(expected_y_float64) assert_array_equal(filtered_y, expected_y) assert filtered_y.dtype == np.uint8 # uint16 y_uint16 = stack.cast_img_uint16(y) with pytest.raises(ValueError): stack.gaussian_filter(y_uint16, 2, allow_negative=True) filtered_y = stack.gaussian_filter(y_uint16, 2) expected_y = stack.cast_img_uint16(expected_y_float64) assert_array_equal(filtered_y, expected_y) assert filtered_y.dtype == np.uint16
def test_background_removal_gaussian(): # float64 y_float64 = stack.cast_img_float64(y) filtered_y_float64 = stack.remove_background_gaussian(y_float64, 2) expected_y_float64 = np.array( [[0., 0., 0.01415845, 0.36227129, 0.], [0., 0., 0.25776265, 0.66404555, 0.43726986], [0., 0., 0.11052949, 0.59626213, 0.], [0., 0.42016172, 0., 0., 0.], [0., 0., 0., 0., 0.]], dtype=np.float64) assert_allclose(filtered_y_float64, expected_y_float64, rtol=1e-6) assert filtered_y_float64.dtype == np.float64 # float32 y_float32 = stack.cast_img_float32(y) filtered_y = stack.remove_background_gaussian(y_float32, 2) expected_y = stack.cast_img_float32(expected_y_float64) assert_allclose(filtered_y, expected_y, rtol=1e-6) assert filtered_y.dtype == np.float32 # uint8 with pytest.raises(ValueError): stack.gaussian_filter(y, 2, allow_negative=True) filtered_y = stack.remove_background_gaussian(y, 2) expected_y = stack.cast_img_uint8(expected_y_float64) assert_array_equal(filtered_y, expected_y) assert filtered_y.dtype == np.uint8 # uint16 y_uint16 = stack.cast_img_uint16(y) with pytest.raises(ValueError): stack.gaussian_filter(y_uint16, 2, allow_negative=True) filtered_y = stack.remove_background_gaussian(y_uint16, 2) expected_y = stack.cast_img_uint16(expected_y_float64) assert_array_equal(filtered_y, expected_y) assert filtered_y.dtype == np.uint16
def build_cyt_relief(image_projected, nuc_labelled, mask_cyt, alpha=0.8): """Compute a 2-d representation of the cytoplasm to be used by watershed algorithm. Cells are represented as watershed, with a low values to the center and maximum values at their borders. The equation used is: relief = alpha * relief_pixel + (1 - alpha) * relief_distance - 'relief_pixel' exploit the differences in pixel intensity values. - 'relief_distance' use the distance from the nuclei. Parameters ---------- image_projected : np.ndarray, np.uint Projected image of the cytoplasm with shape (y, x). nuc_labelled : np.ndarray, Result of the nuclei segmentation with shape (y, x). mask_cyt : np.ndarray, bool Binary mask of the cytoplasm with shape (y, x). alpha : float or int Weight of the pixel intensity values to compute the relief. A value of 0 and 1 respectively return 'relief_distance' and 'relief_pixel'. Returns ------- relief : np.ndarray, np.uint Relief image of the cytoplasm with shape (y, x). """ # check parameters stack.check_array(image_projected, ndim=2, dtype=[np.uint8, np.uint16]) stack.check_array(nuc_labelled, ndim=2, dtype=[np.uint8, np.uint16, np.int64, bool]) stack.check_array(mask_cyt, ndim=2, dtype=[bool]) stack.check_parameter(alpha=(float, int)) # use pixel intensity of the cytoplasm channel to compute the seed. if alpha == 1: relief = image_projected.copy() max_intensity = np.iinfo(image_projected.dtype).max relief = max_intensity - relief relief[nuc_labelled > 0] = 0 relief[mask_cyt == 0] = max_intensity relief = stack.rescale(relief) # use distance from the nuclei elif alpha == 0: binary_mask_nuc = nuc_labelled > 0 relief = ndi.distance_transform_edt(~binary_mask_nuc) relief[mask_cyt == 0] = relief.max() relief = np.true_divide(relief, relief.max(), dtype=np.float32) if image_projected.dtype == np.uint8: relief = stack.cast_img_uint8(relief) else: relief = stack.cast_img_uint16(relief) # use both previous methods elif 0 < alpha < 1: relief_pixel = image_projected.copy() max_intensity = np.iinfo(image_projected.dtype).max relief_pixel = max_intensity - relief_pixel relief_pixel[nuc_labelled > 0] = 0 relief_pixel[mask_cyt == 0] = max_intensity relief_pixel = stack.rescale(relief_pixel) relief_pixel = stack.cast_img_float32(relief_pixel) binary_mask_nuc = nuc_labelled > 0 relief_distance = ndi.distance_transform_edt(~binary_mask_nuc) relief_distance[mask_cyt == 0] = relief_distance.max() relief_distance = np.true_divide(relief_distance, relief_distance.max(), dtype=np.float32) relief = alpha * relief_pixel + (1 - alpha) * relief_distance if image_projected.dtype == np.uint8: relief = stack.cast_img_uint8(relief) else: relief = stack.cast_img_uint16(relief) else: raise ValueError("Parameter 'alpha' is wrong. Must be comprised " "between 0 and 1. Currently 'alpha' is {0}" .format(alpha)) return relief
def prepare_coordinate_data(cyt_coord, nuc_coord, rna_coord): """ Parameters ---------- cyt_coord nuc_coord rna_coord Returns ------- """ # convert coordinates in binary mask surfaces mask_cyt, mask_nuc, _, rna_coord = stack.from_coord_to_surface( cyt_coord=cyt_coord, nuc_coord=nuc_coord, rna_coord=rna_coord, external_coord=True) # get mask cytoplasm outside nucleus mask_cyt_out = mask_cyt.copy() mask_cyt_out[mask_nuc] = False # compute distance maps for the cytoplasm and the nucleus distance_cyt = ndi.distance_transform_edt(mask_cyt) distance_nuc_ = ndi.distance_transform_edt(~mask_nuc) distance_nuc = mask_cyt * distance_nuc_ # cast distance map in float32 distance_cyt = distance_cyt.astype(np.float32) distance_nuc = distance_nuc.astype(np.float32) # normalize distance maps between 0 and 1 distance_cyt_normalized = distance_cyt / distance_cyt.max() distance_cyt_normalized = stack.cast_img_float32(distance_cyt_normalized) distance_nuc_normalized = distance_nuc / distance_nuc.max() distance_nuc_normalized = stack.cast_img_float32(distance_nuc_normalized) # get rna outside nucleus mask_rna_in = mask_nuc[rna_coord[:, 1], rna_coord[:, 2]] rna_coord_out = rna_coord[~mask_rna_in] # get centroids centroid_cyt = _get_centroid_surface(mask_cyt) centroid_nuc = _get_centroid_surface(mask_nuc) if len(rna_coord) == 0: centroid_rna = centroid_cyt.copy() else: centroid_rna = _get_centroid_rna(rna_coord) if len(rna_coord_out) == 0: centroid_rna_out = centroid_cyt.copy() else: centroid_rna_out = _get_centroid_rna(rna_coord_out) # get centroid distance maps distance_cyt_centroid = _get_centroid_distance_map(centroid_cyt, mask_cyt) distance_nuc_centroid = _get_centroid_distance_map(centroid_nuc, mask_cyt) distance_rna_out_centroid = _get_centroid_distance_map( centroid_rna_out, mask_cyt) prepared_inputs = (mask_cyt, mask_nuc, mask_cyt_out, distance_cyt, distance_nuc, distance_cyt_normalized, distance_nuc_normalized, rna_coord_out, centroid_cyt, centroid_nuc, centroid_rna, centroid_rna_out, distance_cyt_centroid, distance_nuc_centroid, distance_rna_out_centroid) return prepared_inputs