From 3c24672ebe9e9f2c3bdd127130132dff940334a4 Mon Sep 17 00:00:00 2001 From: Ruben Verweij Date: Thu, 17 Oct 2019 09:01:09 +0200 Subject: [PATCH] Resolve issue #24 --- nd2reader/parser.py | 8 ++--- nd2reader/reader.py | 83 +++++++------------------------------------- tests/test_reader.py | 9 +++-- 3 files changed, 21 insertions(+), 79 deletions(-) diff --git a/nd2reader/parser.py b/nd2reader/parser.py index baea4e8..3c8c8a1 100644 --- a/nd2reader/parser.py +++ b/nd2reader/parser.py @@ -76,7 +76,7 @@ class Parser(object): except (TypeError): return Frame([], frame_no=frame_number, metadata=self._get_frame_metadata()) else: - return image + return Frame(image, frame_no=frame_number, metadata=self._get_frame_metadata()) def get_image_by_attributes(self, frame_number, field_of_view, channel, z_level, height, width): """Gets an image based on its attributes alone @@ -105,7 +105,7 @@ class Parser(object): except (TypeError): return Frame([], frame_no=frame_number, metadata=self._get_frame_metadata()) else: - return raw_image_data + return Frame(raw_image_data, frame_no=frame_number, metadata=self._get_frame_metadata()) @staticmethod def get_dtype_from_metadata(): @@ -283,14 +283,14 @@ class Parser(object): # other cycle to reduce phototoxicity, but NIS Elements still allocated memory as if we were going to take # them every cycle. if np.any(image_data): - return timestamp, Frame(image_data, metadata=self._get_frame_metadata()) + return timestamp, image_data # If a blank "gap" image is encountered, generate an array of corresponding height and width to avoid # errors with ND2-files with missing frames. Array is filled with nan to reflect that data is missing. else: empty_frame = np.full((height, width), np.nan) warnings.warn('ND2 file contains gap frames which are represented by np.nan-filled arrays; to convert to zeros use e.g. np.nan_to_num(array)') - return timestamp, Frame(empty_frame, metadata=self._get_frame_metadata()) + return timestamp, image_data def _get_frame_metadata(self): """Get the metadata for one frame diff --git a/nd2reader/reader.py b/nd2reader/reader.py index bb3de61..e34885d 100644 --- a/nd2reader/reader.py +++ b/nd2reader/reader.py @@ -54,70 +54,22 @@ class ND2Reader(FramesSequenceND): return 0 def get_frame_2D(self, c=0, t=0, z=0, x=0, y=0, v=0): - """Fallback function for backwards compatibility - """ - return self.get_frame_vczyx(v=v, c=c, t=t, z=z, x=x, y=y) - - def get_frame_vczyx(self, v=None, c=None, t=None, z=None, x=None, y=None): - """Retrieve a frame based on the specified coordinates - Axes order is set by self.bundle_axes, x and y coordinates are ignored, - because we always return Frame objects. + """Gets a given frame using the parser + Args: + x: The x-index (pims expects this) + y: The y-index (pims expects this) + c: The color channel number + t: The frame number + z: The z stack number + v: The field of view index + Returns: + pims.Frame: The requested frame """ - # remove 'x', 'y' from bundle axes and set to width, height - bundle_axes = list(self.bundle_axes) - try: - bundle_axes.remove('x') - except ValueError: - pass - try: - bundle_axes.remove('y') - except ValueError: - pass + # This needs to be set to width/height to return an image x = self.metadata["width"] y = self.metadata["height"] - # make coords dictionary based on function input - coords = dict(v=v, c=c, t=t, z=z) - - # Set appropriate values for None and bundle_axes coords - for dim in coords: - coords[dim] = self._get_possible_coords(dim, coords[dim]) - - # Initialize empty array of Frames of right shape - if len(bundle_axes) > 0: - shape = tuple((len(coords[dim]) for dim in bundle_axes)) - results = np.empty(shape, dtype=Frame) - else: - results = np.empty((1,), dtype=Frame) - - # order for the get_image_by_attributes function - argument_order = dict(t=0, v=1, c=2, z=3) - - # Now, collect the results in the right order - for index, _ in np.ndenumerate(results): - current_coords = [0, 0, 0, 0, y, x] - for dim in coords: - if dim in bundle_axes: - dim_val = coords[dim][index[bundle_axes.index(dim)]] - else: - dim_val = coords[dim][0] - current_coords[argument_order[dim]] = dim_val - - # Actually get the corresponding Frame - results[index] = Frame(self._parser.get_image_by_attributes(*current_coords), metadata=self.metadata) - - if len(bundle_axes) == 0: - return results[0] - - return results - - def _get_possible_coords(self, dim, default): - if dim in self.sizes: - if dim in self.bundle_axes: - return range(self.sizes[dim]) - else: - return [default] if default is not None else range(self.sizes[dim]) - return [None] + return self._parser.get_image_by_attributes(t, v, c, z, y, x) @property def parser(self): @@ -206,16 +158,7 @@ class ND2Reader(FramesSequenceND): # provide the default self.iter_axes = self._guess_default_iter_axis() - self._register_get_frame(self.get_frame_vczyx, 'vczyx') - self._register_get_frame(self.get_frame_vczyx, 'vzyx') - self._register_get_frame(self.get_frame_vczyx, 'vcyx') - self._register_get_frame(self.get_frame_vczyx, 'vyx') - - self._register_get_frame(self.get_frame_vczyx, 'czyx') - self._register_get_frame(self.get_frame_vczyx, 'cyx') - - self._register_get_frame(self.get_frame_vczyx, 'zyx') - self._register_get_frame(self.get_frame_vczyx, 'yx') + self._register_get_frame(self.get_frame_2D, 'yx') def _init_axis_if_exists(self, axis, size, min_size=1): if size >= min_size: diff --git a/tests/test_reader.py b/tests/test_reader.py index f37f738..91f96e5 100644 --- a/tests/test_reader.py +++ b/tests/test_reader.py @@ -44,25 +44,24 @@ class TestReader(unittest.TestCase): timesteps = reader.timesteps self.assertEquals(len(timesteps), 0) - def test_get_frame_2D(self): + def test_get_frame_zero(self): # Best test we can do for now: # test everything up to the actual unpacking of the frame data with ArtificialND2('test_data/test_nd2_reader.nd2') as _: with ND2Reader('test_data/test_nd2_reader.nd2') as reader: with self.assertRaises(struct.error) as exception: - frame = reader.get_frame_2D(c=0, t=0, z=0, x=0, y=0, v=0) + frame = reader[0] self.assertIn('unpack', str(exception.exception)) - def test_get_frame_vczyx(self): + def test_get_frame_2D(self): # Best test we can do for now: # test everything up to the actual unpacking of the frame data with ArtificialND2('test_data/test_nd2_reader.nd2') as _: with ND2Reader('test_data/test_nd2_reader.nd2') as reader: with self.assertRaises(struct.error) as exception: - frame = reader.get_frame_vczyx(c=0, t=0, z=0, x=0, y=0, v=0) + frame = reader.get_frame_2D(c=0, t=0, z=0, x=0, y=0, v=0) self.assertIn('unpack', str(exception.exception)) -