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 test_cast_float64(dtype): # from integer to np.float64 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.float64 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 float64 tensor_float64 = stack.cast_img_float64(tensor) assert tensor_float64.dtype == np.float64 # check value if dtype in [np.uint8, np.uint16, np.uint32, np.uint64]: assert tensor_float64.min() == 0 assert tensor_float64.max() == 1 elif dtype in [np.int8, np.int16, np.int32, np.int64]: assert tensor_float64.min() == -1 assert tensor_float64.max() == 1 else: assert_array_almost_equal(tensor_float64, tensor)
def test_cast_float64(dtype): # from integer to np.float64 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.float64 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 float64 tensor_float64 = stack.cast_img_float64(tensor) assert tensor_float64.dtype == np.float64
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 get_watershed_relief(image, nuc_label, alpha): """Build a representation of cells as watershed. In a watershed algorithm we consider cells as watershed to be flooded. The watershed relief is inversely proportional to both the pixel intensity and the closeness to nuclei. Pixels with a high intensity or close to labelled nuclei have a low watershed relief value. They will be flooded in priority. Flooding the watersheds allows to propagate nuclei labels through potential cytoplasm areas. The lines separating watershed are the final segmentation of the cells. Parameters ---------- image : np.ndarray, np.uint Cells image with shape (z, y, x) or (y, x). nuc_label : np.ndarray, np.int64 Result of the nuclei segmentation with shape (y, x) and nuclei instances labelled. alpha : float or int Weight of the pixel intensity values to compute the relief. Returns ------- watershed_relief : np.ndarray, np.uint16 Watershed representation of cells with shape (y, x). """ # check parameters stack.check_array(image, ndim=[2, 3], dtype=[np.uint8, np.uint16]) stack.check_array(nuc_label, ndim=2, dtype=np.int64) stack.check_parameter(alpha=(int, float)) # use pixel intensity of the cells image if alpha == 1: # if a 3-d image is provided we sum its pixel values image = stack.cast_img_float64(image) if image.ndim == 3: image = image.sum(axis=0) # rescale image image = stack.rescale(image) # build watershed relief watershed_relief = image.max() - image watershed_relief[nuc_label > 0] = 0 watershed_relief = np.true_divide(watershed_relief, watershed_relief.max(), dtype=np.float64) watershed_relief = stack.cast_img_uint16(watershed_relief, catch_warning=True) # use distance from the nuclei elif alpha == 0: # build watershed relief nuc_mask = nuc_label > 0 watershed_relief = ndi.distance_transform_edt(~nuc_mask) watershed_relief = np.true_divide(watershed_relief, watershed_relief.max(), dtype=np.float64) watershed_relief = stack.cast_img_uint16(watershed_relief, catch_warning=True) # use a combination of both previous methods elif 0 < alpha < 1: # if a 3-d image is provided we sum its pixel values image = stack.cast_img_float64(image) if image.ndim == 3: image = image.sum(axis=0) # rescale image image = stack.rescale(image) # build watershed relief relief_pixel = image.max() - image relief_pixel[nuc_label > 0] = 0 relief_pixel = np.true_divide(relief_pixel, relief_pixel.max(), dtype=np.float64) nuc_mask = nuc_label > 0 relief_distance = ndi.distance_transform_edt(~nuc_mask) relief_distance = np.true_divide(relief_distance, relief_distance.max(), dtype=np.float64) watershed_relief = alpha * relief_pixel + (1 - alpha) * relief_distance watershed_relief = stack.cast_img_uint16(watershed_relief, catch_warning=True) else: raise ValueError("Parameter 'alpha' is wrong. It must be comprised " "between 0 and 1. Currently 'alpha' is {0}" .format(alpha)) return watershed_relief