From 1a762d7ed853eef1698ad2951e586cd226650bfc Mon Sep 17 00:00:00 2001 From: Arin Wongprommoon <arin.wongprommoon@ed.ac.uk> Date: Tue, 17 Jan 2023 11:38:20 +0000 Subject: [PATCH] fix!(aliby): incorporate ref_z in creating dummy image object WHY IS THIS CHANGE NEEDED?: - using dev_testimage.py in skeletons: when dummy tiler is created and tiler.initialise_traps() is invoked, segment_traps() (still) raises 'No valid 'tiling regions found' HOW DOES THE CHANGE SOLVE THE PROBLEM?: - in tiler.initialise_traps(), initial_image was defined based on self.ref_channel and self.ref_z; however, if ref_z was not 0, then initial_image would be a zero array. - this was because ImageDummy.pad_array() put the input image at the 0 position and pads with zeros regardless of the value of ref_z. - so i wanted the output of ImageDummy.get_data_lazy() to be defined in such a way that the (ref_z)th slice in the z-direction is the input image. - therefore, i added a new argument to Image.Dummy.pad_array() so that ref_z can be used to achieve the above. WHAT SIDE EFFECTS DOES THIS CHANGE HAVE?: - tech debt: no (easy) way to deal with ref_channel because it's a string. workaround is to keep the ref_channel the first channel in the dummy tiler, and assume that throughout. EVIDENCE THAT COMMIT WORKS: - modified test_image.py works - skeletons: dummy tiler can be defined and dummy_tiler._run_tp(0) runs without errors --- src/aliby/io/image.py | 27 ++++++++++++++++++++++----- src/aliby/tile/tiler.py | 3 ++- tests/aliby/pipeline/test_image.py | 12 ++++++++---- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/aliby/io/image.py b/src/aliby/io/image.py index 0bd41880..da563f3e 100644 --- a/src/aliby/io/image.py +++ b/src/aliby/io/image.py @@ -138,7 +138,12 @@ class ImageDummy(BaseLocalImage): # Goal: make Tiler happy. @staticmethod - def pad_array(image_array: da.Array, dim: int, n_empty_slices: int): + def pad_array( + image_array: da.Array, + dim: int, + n_empty_slices: int, + image_position: int = 0, + ): """Extends a dimension in a dask array and pads with zeros Extends a dimension in a dask array that has existing content, then pads @@ -153,19 +158,29 @@ class ImageDummy(BaseLocalImage): n_empty_slices : int Number of empty slices to extend the dask array by, in the specified dimension/axis. + image_position : int + Position within the new dimension to place the input arary, default 0 + (the beginning). Examples -------- ``` - extended_array = pad_array(my_da_array, dim = 2, n_empty_slices = 4) + extended_array = pad_array( + my_da_array, dim = 2, n_empty_slices = 4, image_position = 1) ``` Extends a dask array called `my_da_array` in the 3rd dimension - (dimensions start from 0) by 4 slices, filled with zeros. + (dimensions start from 0) by 4 slices, filled with zeros. And puts the + original content in slice 1 of the 3rd dimension """ # Concats zero arrays with same dimensions as image_array, and puts # image_array as first element in list of arrays to be concatenated + zeros_array = da.zeros_like(image_array) return da.concatenate( - [image_array, *([da.zeros_like(image_array)] * n_empty_slices)], + [ + *([zeros_array] * image_position), + image_array, + *([zeros_array] * (n_empty_slices - image_position)), + ], axis=dim, ) @@ -192,7 +207,9 @@ class ImageDummy(BaseLocalImage): img, dim=0, n_empty_slices=199 ) # 200 timepoints total img = self.pad_array(img, dim=1, n_empty_slices=2) # 3 channels - img = self.pad_array(img, dim=2, n_empty_slices=4) # 5 z-stacks + img = self.pad_array( + img, dim=2, n_empty_slices=4, image_position=self.ref_z + ) # 5 z-stacks return img def name(self): diff --git a/src/aliby/tile/tiler.py b/src/aliby/tile/tiler.py index 9de61621..93ae8cc4 100644 --- a/src/aliby/tile/tiler.py +++ b/src/aliby/tile/tiler.py @@ -258,6 +258,7 @@ class Tiler(StepABC): """ imgdmy_obj = ImageDummy(parameters) dummy_image = imgdmy_obj.get_data_lazy() + # FIXME: TECHNICAL DEBT: hard-coding dimension orders dummy_omero_metadata = { "size_x": dummy_image.shape[3], "size_y": dummy_image.shape[4], @@ -265,8 +266,8 @@ class Tiler(StepABC): "size_c": dummy_image.shape[1], "size_t": dummy_image.shape[0], "channels": [ - *(["nil"] * (dummy_image.shape[1] - 1)), parameters["ref_channel"], + *(["nil"] * (dummy_image.shape[1] - 1)), ], "name": " ", } diff --git a/tests/aliby/pipeline/test_image.py b/tests/aliby/pipeline/test_image.py index d8343a5d..3a211400 100644 --- a/tests/aliby/pipeline/test_image.py +++ b/tests/aliby/pipeline/test_image.py @@ -17,23 +17,27 @@ sample_da = da.reshape( @pytest.mark.parametrize("sample_da", [sample_da]) @pytest.mark.parametrize("dim", [2]) @pytest.mark.parametrize("n_empty_slices", [4]) -def test_pad_array(sample_da, dim, n_empty_slices): +@pytest.mark.parametrize("image_position", [1]) +def test_pad_array(sample_da, dim, n_empty_slices, image_position): """Test ImageDummy.pad_array() method""" # create object imgdmy = ImageDummy(tiler_parameters) # pads array padded_da = imgdmy.pad_array( - sample_da, dim=dim, n_empty_slices=n_empty_slices + sample_da, + dim=dim, + n_empty_slices=n_empty_slices, + image_position=image_position, ) # select which dimension to index the multidimensional array - indices = {dim: 0} + indices = {dim: image_position} ix = [ indices.get(dim, slice(None)) for dim in range(padded_da.compute().ndim) ] - # Checks that original image array is there and is at the first index + # Checks that original image array is there and is at the correct index assert np.array_equal(padded_da.compute()[ix], sample_da.compute()[0]) # Checks that the additional axis is extended correctly assert padded_da.compute().shape[dim] == n_empty_slices + 1 -- GitLab