diff --git a/nd2reader/__init__.py b/nd2reader/__init__.py index 64cff75..2d8af1a 100644 --- a/nd2reader/__init__.py +++ b/nd2reader/__init__.py @@ -1,3 +1,4 @@ from nd2reader.reader import ND2Reader +from nd2reader.legacy import Nd2 __version__ = '2.1.3' diff --git a/nd2reader/legacy.py b/nd2reader/legacy.py new file mode 100644 index 0000000..8764ab0 --- /dev/null +++ b/nd2reader/legacy.py @@ -0,0 +1,149 @@ +""" +Legacy class for backwards compatibility +""" + +import warnings + +from nd2reader import ND2Reader + + +class Nd2(object): + """ Legacy Nd2 object for backwards compatibility. """ + + def __init__(self, filename): + warnings.warn( + "The 'Nd2' class is deprecated, please consider using the new ND2Reader interface which uses pims.", + DeprecationWarning) + + self.reader = ND2Reader(filename) + + def __repr__(self): + return "\n".join(["" % self.reader.filename, + "Created: %s" % (self.date if self.date is not None else "Unknown"), + "Image size: %sx%s (HxW)" % (self.height, self.width), + "Frames: %s" % len(self.frames), + "Channels: %s" % ", ".join(["%s" % str(channel) for channel in self.channels]), + "Fields of View: %s" % len(self.fields_of_view), + "Z-Levels: %s" % len(self.z_levels) + ]) + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.reader is not None: + self.reader.close() + + def __len__(self): + return len(self.reader) + + def __getitem__(self, item): + return self.reader[item] + + def select(self, fields_of_view=None, channels=None, z_levels=None, start=0, stop=None): + """ + Select images based on criteria. + Args: + fields_of_view: the fields of view + channels: the color channels + z_levels: the z levels + start: the starting frame + stop: the last frame + + Returns: + ND2Reader: Sliced ND2Reader which contains the frames + """ + if stop is None: + stop = len(self.frames) + + return self.reader[start:stop] + + def get_image(self, frame_number, field_of_view, channel_name, z_level): + """ + Deprecated. Returns the specified image from the ND2Reader class. + Args: + frame_number: the frame number + field_of_view: the field of view number + channel_name: the name of the color channel + z_level: the z level number + """ + return self.reader.parser.get_image_by_attributes(frame_number, field_of_view, channel_name, z_level, + self.height, self.width) + + def close(self): + """Closes the ND2Reader + """ + if self.reader is not None: + self.reader.close() + + @property + def height(self): + """ + Deprecated. Fetches the height of the image. + Returns: + int: the pixel height of the image + """ + return self.reader.metadata["height"] + + @property + def width(self): + """ + Deprecated. Fetches the width of the image. + Returns: + int: the pixel width of the image + """ + return self.reader.metadata["width"] + + @property + def z_levels(self): + """ + Deprecated. Fetches the available z levels. + Returns: + list: z levels. + """ + return self.reader.metadata["z_levels"] + + @property + def fields_of_view(self): + """ + Deprecated. Fetches the fields of view. + Returns: + list: fields of view. + """ + return self.reader.metadata["fields_of_view"] + + @property + def channels(self): + """ + Deprecated. Fetches all color channels. + Returns: + list: the color channels. + """ + return self.reader.metadata["channels"] + + @property + def frames(self): + """ + Deprecated. Fetches all frames. + Returns: + list: list of frames + """ + return self.reader.metadata["frames"] + + @property + def date(self): + """ + Deprecated. Fetches the acquisition date. + Returns: + string: the date + """ + return self.reader.metadata["date"] + + @property + def pixel_microns(self): + """ + Deprecated. Fetches the amount of microns per pixel. + Returns: + float: microns per pixel + """ + return self.reader.metadata["pixel_microns"] diff --git a/nd2reader/reader.py b/nd2reader/reader.py index bc11034..24a102e 100644 --- a/nd2reader/reader.py +++ b/nd2reader/reader.py @@ -89,6 +89,15 @@ class ND2Reader(FramesSequenceND): c_name = self.metadata["channels"][c] return self._parser.get_image_by_attributes(t, 0, c_name, z, self.metadata["height"], self.metadata["width"]) + @property + def parser(self): + """ + Returns the parser object. + Returns: + Parser: the parser object + """ + return self._parser + @property def pixel_type(self): """Return the pixel data type diff --git a/tests/test_legacy.py b/tests/test_legacy.py new file mode 100644 index 0000000..67f15e8 --- /dev/null +++ b/tests/test_legacy.py @@ -0,0 +1,44 @@ +""" +Unit test for backwards compatibility. +""" +import unittest +from os import path + +from nd2reader.legacy import Nd2 + + +class TestReader(unittest.TestCase): + def setUp(self): + dir_path = path.dirname(path.realpath(__file__)) + self.files = [ + path.join(dir_path, 'test_data/data001.nd2'), + path.join(dir_path, 'test_data/data002.nd2') + ] + + def test_sizes_data_001(self): + with Nd2(self.files[0]) as reader: + self.assertEqual(reader.width, 128) + self.assertEqual(reader.height, 128) + self.assertEqual(len(reader.frames), 982) + self.assertEqual(len(reader.channels), 1) + self.assertEqual(len(reader.z_levels), 1) + + def test_frame_size_data_001(self): + with Nd2(self.files[0]) as reader: + frame = reader[13] + self.assertEqual(frame.shape[0], 128) + self.assertEqual(frame.shape[1], 128) + + def test_sizes_data_002(self): + with Nd2(self.files[1]) as reader: + self.assertEqual(reader.width, 512) + self.assertEqual(reader.height, 256) + self.assertEqual(len(reader.frames), 78) + self.assertEqual(len(reader.channels), 1) + self.assertEqual(len(reader.z_levels), 1) + + def test_frame_size_data_002(self): + with Nd2(self.files[1]) as reader: + frame = reader[13] + self.assertEqual(frame.shape[1], 512) + self.assertEqual(frame.shape[0], 256)