Skip to content
Snippets Groups Projects
Commit efe1e45c authored by Christopher Randolph Rhodes's avatar Christopher Randolph Rhodes
Browse files

Product methods call RoiSet directly; this is causing problems with...

Product methods call RoiSet directly; this is causing problems with multichannel ones where raw data is essentially re-issues to RGB channels
parent 7ce760c7
No related branches found
No related tags found
No related merge requests found
...@@ -85,8 +85,9 @@ def export_patch_masks(roiset, where: Path, pad_to: int = 256, prefix='mask') -> ...@@ -85,8 +85,9 @@ def export_patch_masks(roiset, where: Path, pad_to: int = 256, prefix='mask') ->
def get_patches_from_zmask_meta( def get_patches_from_zmask_meta(
stack: GenericImageDataAccessor, # stack: GenericImageDataAccessor,
zmask_meta: list, # zmask_meta: list,
roiset,
rescale_clip: float = 0.0, rescale_clip: float = 0.0,
pad_to: int = 256, pad_to: int = 256,
make_3d: bool = False, make_3d: bool = False,
...@@ -95,22 +96,23 @@ def get_patches_from_zmask_meta( ...@@ -95,22 +96,23 @@ def get_patches_from_zmask_meta(
) -> MonoPatchStack: ) -> MonoPatchStack:
patches = [] patches = []
for mi in zmask_meta: # for mi in zmask_meta:
for i, roi in enumerate(roiset.get_df().itertuples()):
sl = mi['slice']
rbb = mi['relative_bounding_box'] # TODO: call rel_ fields in DF # sl = roi['slice']
idx = mi['df_index'] # rbb = mi['relative_bounding_box'] # TODO: call rel_ fields in DF
# idx = mi['df_index']
x0 = rbb['x0'] #
y0 = rbb['y0'] # x0 = rbb['x0']
x1 = rbb['x1'] # y0 = rbb['y0']
y1 = rbb['y1'] # x1 = rbb['x1']
# y1 = rbb['y1']
sp_sl = np.s_[y0: y1, x0: x1, :, :] #
# sp_sl = np.s_[y0: y1, x0: x1, :, :]
patch3d = stack.data[sl]
patch3d = roiset.acc_raw.data[roi.slice]
ph, pw, pc, pz = patch3d.shape ph, pw, pc, pz = patch3d.shape
subpatch = patch3d[sp_sl] subpatch = patch3d[roi.relative_slice]
# make a 3d patch # make a 3d patch
if make_3d: if make_3d:
...@@ -133,7 +135,7 @@ def get_patches_from_zmask_meta( ...@@ -133,7 +135,7 @@ def get_patches_from_zmask_meta(
patch = patch3d[:, :, :, [zim]] patch = patch3d[:, :, :, [zim]]
assert len(patch.shape) == 4 assert len(patch.shape) == 4
assert patch.shape[2] == stack.chroma assert patch.shape[2] == roiset.acc_raw.chroma
if rescale_clip is not None: if rescale_clip is not None:
patch = rescale(patch, rescale_clip) patch = rescale(patch, rescale_clip)
...@@ -146,21 +148,21 @@ def get_patches_from_zmask_meta( ...@@ -146,21 +148,21 @@ def get_patches_from_zmask_meta(
for zi in range(0, patch.shape[3]): for zi in range(0, patch.shape[3]):
patch[:, :, bci, zi] = draw_box_on_patch( patch[:, :, bci, zi] = draw_box_on_patch(
patch[:, :, bci, zi], patch[:, :, bci, zi],
((x0, y0), (x1, y1)), ((roi.rel_x0, roi.rel_y0), (roi.rel_x1, roi.rel_y1)),
linewidth=kwargs.get('bounding_box_linewidth', 1) linewidth=kwargs.get('bounding_box_linewidth', 1)
) )
if kwargs.get('draw_mask'): if kwargs.get('draw_mask'):
mci = kwargs.get('mask_channel', 0) mci = kwargs.get('mask_channel', 0)
mask = np.zeros(patch.shape[0:2], dtype=bool) mask = np.zeros(patch.shape[0:2], dtype=bool)
mask[sp_sl[0:2]] = mi['mask'] mask[roi.relative_slice[0:2]] = roi.mask
for zi in range(0, patch.shape[3]): for zi in range(0, patch.shape[3]):
patch[:, :, mci, zi] = np.invert(mask) * patch[:, :, mci, zi] patch[:, :, mci, zi] = np.invert(mask) * patch[:, :, mci, zi]
if kwargs.get('draw_contour'): if kwargs.get('draw_contour'):
mci = kwargs.get('contour_channel', 0) mci = kwargs.get('contour_channel', 0)
mask = np.zeros(patch.shape[0:2], dtype=bool) mask = np.zeros(patch.shape[0:2], dtype=bool)
mask[sp_sl[0:2]] = mi['mask'] mask[roi.relative_slice[0:2]] = roi.mask
for zi in range(0, patch.shape[3]): for zi in range(0, patch.shape[3]):
patch[:, :, mci, zi] = draw_contours_on_patch( patch[:, :, mci, zi] = draw_contours_on_patch(
...@@ -180,8 +182,9 @@ def get_patches_from_zmask_meta( ...@@ -180,8 +182,9 @@ def get_patches_from_zmask_meta(
def export_patches_from_zstack( def export_patches_from_zstack(
where: Path, where: Path,
stack: GenericImageDataAccessor, # stack: GenericImageDataAccessor,
zmask_meta: list, # zmask_meta: list,
roiset,
rescale_clip: float = 0.0, rescale_clip: float = 0.0,
pad_to: int = 256, pad_to: int = 256,
make_3d: bool = False, make_3d: bool = False,
...@@ -190,24 +193,25 @@ def export_patches_from_zstack( ...@@ -190,24 +193,25 @@ def export_patches_from_zstack(
**kwargs **kwargs
): ):
patches_acc = get_patches_from_zmask_meta( patches_acc = get_patches_from_zmask_meta(
stack, roiset,
zmask_meta, # stack,
rescale_clip=rescale_clip, # zmask_meta,
# rescale_clip=rescale_clip,
pad_to=pad_to, pad_to=pad_to,
make_3d=make_3d, make_3d=make_3d,
focus_metric=focus_metric, focus_metric=focus_metric,
**kwargs **kwargs
) )
assert len(zmask_meta) == patches_acc.count
exported = [] exported = []
for i in range(0, len(zmask_meta)): for i, roi in enumerate(roiset.get_df().itertuples()):
mi = zmask_meta[i] # for i in range(0, len(zmask_meta)):
# mi = zmask_meta[i]
patch = patches_acc.iat_yxcz(i) patch = patches_acc.iat_yxcz(i)
obj = mi['info'] # obj = mi['info']
idx = mi['df_index'] # idx = mi['df_index']
ext = 'tif' if make_3d else 'png' ext = 'tif' if make_3d else 'png'
fname = f'{prefix}-la{obj.label:04d}-zi{obj.zi:04d}.{ext}' fname = f'{prefix}-la{roi.label:04d}-zi{roi.zi:04d}.{ext}'
if patch.dtype is np.dtype('uint16'): if patch.dtype is np.dtype('uint16'):
write_patch_to_file(where, fname, resample_to_8bit(patch)) write_patch_to_file(where, fname, resample_to_8bit(patch))
...@@ -215,7 +219,7 @@ def export_patches_from_zstack( ...@@ -215,7 +219,7 @@ def export_patches_from_zstack(
write_patch_to_file(where, fname, patch) write_patch_to_file(where, fname, patch)
exported.append({ exported.append({
'df_index': idx, 'df_index': roi.Index,
'patch_filename': fname, 'patch_filename': fname,
}) })
return exported return exported
...@@ -303,8 +307,7 @@ def export_3d_patches_with_focus_metrics( ...@@ -303,8 +307,7 @@ def export_3d_patches_with_focus_metrics(
def export_multichannel_patches_from_zstack( def export_multichannel_patches_from_zstack(
where: Path, where: Path,
stack: GenericImageDataAccessor, roiset,
zmask_meta: list,
rgb_overlay_channels: list = None, rgb_overlay_channels: list = None,
rgb_overlay_weights: list = [1.0, 1.0, 1.0], rgb_overlay_weights: list = [1.0, 1.0, 1.0],
ch_white: int = None, ch_white: int = None,
...@@ -327,9 +330,9 @@ def export_multichannel_patches_from_zstack( ...@@ -327,9 +330,9 @@ def export_multichannel_patches_from_zstack(
np.iinfo(a.dtype).max np.iinfo(a.dtype).max
).astype(a.dtype) ).astype(a.dtype)
idata = stack.data idata = roiset.acc_raw.data
if ch_white: if ch_white:
assert ch_white < stack.chroma assert ch_white < roiset.acc_raw.chroma
mdata = idata[:, :, [ch_white, ch_white, ch_white], :] mdata = idata[:, :, [ch_white, ch_white, ch_white], :]
else: else:
mdata = idata mdata = idata
...@@ -341,14 +344,14 @@ def export_multichannel_patches_from_zstack( ...@@ -341,14 +344,14 @@ def export_multichannel_patches_from_zstack(
if ci is None: if ci is None:
continue continue
assert isinstance(ci, int) assert isinstance(ci, int)
assert ci < stack.chroma assert ci < roiset.acc_raw.chroma
mdata[:, :, ii, :] = _safe_add( mdata[:, :, ii, :] = _safe_add(
mdata[:, :, ii, :], mdata[:, :, ii, :],
rgb_overlay_weights[ii], rgb_overlay_weights[ii],
idata[:, :, ci, :] idata[:, :, ci, :]
) )
# TODO: this is a bit of a workaround
mstack = InMemoryDataAccessor(mdata) mstack = InMemoryDataAccessor(mdata)
return export_patches_from_zstack( rgb_roiset = RoiSet(roiset.acc_obj_ids, mstack, roiset.params)
where, mstack, zmask_meta, **kwargs return export_patches_from_zstack(where, rgb_roiset, **kwargs)
) \ No newline at end of file
\ No newline at end of file
...@@ -119,8 +119,7 @@ class TestZStackDerivedDataProducts(unittest.TestCase): ...@@ -119,8 +119,7 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
) )
files = export_patches_from_zstack( files = export_patches_from_zstack(
output_path / '2d_patches', output_path / '2d_patches',
self.stack_ch_pa, roiset,
roiset.zmask_meta,
draw_bounding_box=True, draw_bounding_box=True,
) )
self.assertGreaterEqual(len(files), 1) self.assertGreaterEqual(len(files), 1)
...@@ -132,8 +131,9 @@ class TestZStackDerivedDataProducts(unittest.TestCase): ...@@ -132,8 +131,9 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
) )
files = export_patches_from_zstack( files = export_patches_from_zstack(
output_path / '3d_patches', output_path / '3d_patches',
self.stack_ch_pa, # self.stack_ch_pa,
roiset.zmask_meta, roiset,
# roiset.zmask_meta,
make_3d=True) make_3d=True)
self.assertGreaterEqual(len(files), 1) self.assertGreaterEqual(len(files), 1)
...@@ -162,15 +162,26 @@ class TestZStackDerivedDataProducts(unittest.TestCase): ...@@ -162,15 +162,26 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
InMemoryDataAccessor(img) 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(
mask_type=mask_type, filters=kwargs.get('filters')
)
)
def test_make_multichannel_2d_patches_from_zmask(self): def test_make_multichannel_2d_patches_from_zmask(self):
roiset = self.test_zmask_makes_correct_boxes( roiset = self._setup_multichannel_tests(
filters={'area': {'min': 1e3, 'max': 1e4}}, filters={'area': {'min': 1e3, 'max': 1e4}},
expand_box_by=(128, 2) expand_box_by=(128, 2)
) )
files = export_multichannel_patches_from_zstack( files = export_multichannel_patches_from_zstack(
output_path / '2d_patches_chlorophyl_bbox_overlay', output_path / '2d_patches_chlorophyl_bbox_overlay',
InMemoryDataAccessor(self.stack.data), # InMemoryDataAccessor(self.stack.data),
roiset.zmask_meta, # roiset.zmask_meta,
roiset,
ch_white=4, ch_white=4,
draw_bounding_box=True, draw_bounding_box=True,
bounding_box_channel=1, bounding_box_channel=1,
...@@ -184,8 +195,9 @@ class TestZStackDerivedDataProducts(unittest.TestCase): ...@@ -184,8 +195,9 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
) )
files = export_multichannel_patches_from_zstack( files = export_multichannel_patches_from_zstack(
output_path / '2d_patches_chlorophyl_mask_overlay', output_path / '2d_patches_chlorophyl_mask_overlay',
InMemoryDataAccessor(self.stack.data), # InMemoryDataAccessor(self.stack.data),
roiset.zmask_meta, # roiset.zmask_meta,
roiset,
ch_white=4, ch_white=4,
ch_rgb_overlay=(3, None, None), ch_rgb_overlay=(3, None, None),
draw_mask=True, draw_mask=True,
...@@ -201,8 +213,8 @@ class TestZStackDerivedDataProducts(unittest.TestCase): ...@@ -201,8 +213,8 @@ class TestZStackDerivedDataProducts(unittest.TestCase):
) )
files = export_multichannel_patches_from_zstack( files = export_multichannel_patches_from_zstack(
output_path / '2d_patches_chlorophyl_contour_overlay', output_path / '2d_patches_chlorophyl_contour_overlay',
InMemoryDataAccessor(self.stack.data), # InMemoryDataAccessor(self.stack.data),
roiset.zmask_meta, roiset,
ch_white=4, ch_white=4,
ch_rgb_overlay=(3, None, None), ch_rgb_overlay=(3, None, None),
draw_contour=True, draw_contour=True,
......
...@@ -34,6 +34,7 @@ class RoiSet(object): ...@@ -34,6 +34,7 @@ class RoiSet(object):
): ):
self.acc_obj_ids = acc_obj_ids self.acc_obj_ids = acc_obj_ids
self.acc_raw = acc_raw self.acc_raw = acc_raw
self.params = params
self._df = self.filter_df( self._df = self.filter_df(
self.make_df( self.make_df(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment