diff --git a/model_server/extensions/chaeo/products.py b/model_server/extensions/chaeo/products.py index 3027f97cbfd1215ed222a4e8117b5af9f3a6cdd7..4b0d197f6a859c7cc88c03d3089799542e8fa2d9 100644 --- a/model_server/extensions/chaeo/products.py +++ b/model_server/extensions/chaeo/products.py @@ -118,7 +118,7 @@ def get_patches_from_zmask_meta( assert white_channel < raw.chroma stack = raw.data[:, :, [white_channel, white_channel, white_channel], :] else: - stack = np.zeros([*raw.shape[0:1], 3, raw.shape[3]], dtype=raw.dtype) + stack = np.zeros([*raw.shape[0:2], 3, raw.shape[3]], dtype=raw.dtype) for ii, ci in enumerate(rgb_overlay_channels): if ci is None: @@ -128,12 +128,24 @@ def get_patches_from_zmask_meta( stack[:, :, ii, :] = _safe_add( stack[:, :, ii, :], # either black or grayscale channel rgb_overlay_weights[ii], - stack[:, :, ci, :] + raw.data[:, :, ci, :] ) else: - if white_channel: + if white_channel: # interpret as just a single channel assert white_channel < raw.chroma - stack = raw.data[:, :, [white_channel], :] + annotate_rgb = False + for k in ['contour_channel', 'bounding_box_channel', 'mask_channel']: + ca = kwargs.get(k) + if ca is None: + continue + assert(ca < raw.chroma) + if ca != white_channel: + annotate_rgb = True + break + if annotate_rgb: # make RGB patches anyway to include annotation color + stack = raw.data[:, :, [white_channel, white_channel, white_channel], :] + else: # make monochrome patches + stack = raw.data[:, :, [white_channel], :] else: stack = raw.data diff --git a/model_server/extensions/chaeo/tests/test_zstack.py b/model_server/extensions/chaeo/tests/test_zstack.py index 816c3f25eb5e56f019741097486cc8e512c5ccc5..6cf76c9c9e783f06948d2a8c6c655aec752cf7b0 100644 --- a/model_server/extensions/chaeo/tests/test_zstack.py +++ b/model_server/extensions/chaeo/tests/test_zstack.py @@ -39,6 +39,17 @@ class TestZStackDerivedDataProducts(unittest.TestCase): ) write_accessor_data_to_file(output_path / 'seg_mask.tif', self.seg_mask) + id_map = get_label_ids(self.seg_mask) + self.roiset = RoiSet( + id_map, + self.stack, + params=RoiSetMetaParams( + expand_box_by=(128, 2), + mask_type='boxes', + filters={'area': {'min': 1e3, 'max': 1e4}}, + ) + ) + def test_zmask_makes_correct_boxes(self, mask_type='boxes', **kwargs): id_map = get_label_ids(self.seg_mask) roiset = RoiSet( @@ -159,34 +170,20 @@ class TestZStackDerivedDataProducts(unittest.TestCase): InMemoryDataAccessor(img) ) - def _setup_multichannel_tests(self, mask_type='boxes', **kwargs): - id_map = get_label_ids(self.seg_mask) - return RoiSet( - id_map, - self.stack, - params=RoiSetMetaParams( - expand_box_by=(128, 2), - mask_type=mask_type, - filters={'area': {'min': 1e3, 'max': 1e4}}, - ) - ) - - def test_make_mono_2d_patches_from_multichannel_zmask(self): - roiset = self._setup_multichannel_tests() + def test_multichannel_to_mono_2d_patches(self): files = export_multichannel_patches_from_zstack( - output_path / 'test_make_mono_2d_patches_from_multichannel_zmask', - roiset, + output_path / 'test_multichannel_to_mono_2d_patches', + self.roiset, white_channel=3, draw_bounding_box=True, ) result = generate_file_accessor(Path(files[0]['location']) / files[0]['patch_filename']) self.assertEqual(result.chroma, 1) - def test_make_rgb_annotated_mono_2d_patches_from_multichannel_zmask(self): - roiset = self._setup_multichannel_tests() + def test_multichannnel_to_mono_2d_patches_rgb_bbox(self): files = export_multichannel_patches_from_zstack( - output_path / 'test_make_rgb_annotated_mono_2d_patches_from_multichannel_zmask', - roiset, + output_path / 'multichannnel_to_mono_2d_patches_rgb_bbox', + self.roiset, white_channel=3, draw_bounding_box=True, bounding_box_channel=1, @@ -194,11 +191,10 @@ class TestZStackDerivedDataProducts(unittest.TestCase): result = generate_file_accessor(Path(files[0]['location']) / files[0]['patch_filename']) self.assertEqual(result.chroma, 3) - def test_make_multichannel_2d_patches_with_mask_overlay(self): - roiset = self._setup_multichannel_tests() + def test_multichannnel_to_rgb_2d_patches_bbox(self): files = export_multichannel_patches_from_zstack( - output_path / 'test_make_multichannel_2d_patches_with_mask_overlay', - roiset, + output_path / 'multichannnel_to_rgb_2d_patches_bbox', + self.roiset, white_channel=4, rgb_overlay_channels=(3, None, None), draw_mask=True, @@ -208,26 +204,24 @@ class TestZStackDerivedDataProducts(unittest.TestCase): result = generate_file_accessor(Path(files[0]['location']) / files[0]['patch_filename']) self.assertEqual(result.chroma, 3) - def test_make_multichannel_2d_patches_with_contour_overlay(self): - roiset = self._setup_multichannel_tests() + def test_multichannnel_to_rgb_2d_patches_contour(self): files = export_multichannel_patches_from_zstack( - output_path / '2d_patches_chlorophyl_contour_overlay', - # InMemoryDataAccessor(self.stack.data), - roiset, - rgb_white_channel=4, - ch_rgb_overlay=(3, None, None), + output_path / 'multichannnel_to_rgb_2d_patches_contour', + self.roiset, + rgb_overlay_channels=(3, None, None), draw_contour=True, contour_channel=1, - overlay_gain=(0.1, 1.0, 1.0) + rgb_overlay_weights=(0.1, 1.0, 1.0) ) result = generate_file_accessor(Path(files[0]['location']) / files[0]['patch_filename']) self.assertEqual(result.chroma, 3) + self.assertEqual(result.get_one_channel_data(2).data.max(), 0) # blue channel is black - def test_make_2d_patches_as_multichannel_tif(self): - roiset = self._setup_multichannel_tests() + def test_multichannel_to_multichannel_tif_patches(self): + # roiset = self._setup_multichannel_tests() files = export_multichannel_patches_from_zstack( - output_path / '2d_patches_multichannel_tif', - roiset, + output_path / 'multichannel_to_multichannel_tif_patches', + self.roiset, ) result = generate_file_accessor(Path(files[0]['location']) / files[0]['patch_filename']) self.assertEqual(result.chroma, 5)