diff --git a/nd2reader/__init__.py b/nd2reader/__init__.py index c0d16d9..4ef37c4 100644 --- a/nd2reader/__init__.py +++ b/nd2reader/__init__.py @@ -1,16 +1,14 @@ # -*- coding: utf-8 -*- -import logging from nd2reader.model import Image, ImageSet from nd2reader.parser import Nd2Parser -log = logging.getLogger(__name__) -log.addHandler(logging.StreamHandler()) -log.setLevel(logging.WARNING) - - class Nd2(Nd2Parser): + """ + Allows easy access to NIS Elements .nd2 image files. + + """ def __init__(self, filename): super(Nd2, self).__init__(filename) self._filename = filename @@ -25,7 +23,31 @@ class Nd2(Nd2Parser): "Z-Levels: %s" % self._z_level_count ]) + @property + def height(self): + """ + :return: height of each image, in pixels + :rtype: int + + """ + return self.metadata['ImageAttributes']['SLxImageAttributes']['uiHeight'] + + @property + def width(self): + """ + :return: width of each image, in pixels + :rtype: int + + """ + return self.metadata['ImageAttributes']['SLxImageAttributes']['uiWidth'] + def __iter__(self): + """ + Iterates over every image, in the order they were taken. + + :return: model.Image() + + """ for i in range(self._image_count): for fov in range(self._field_of_view_count): for z_level in range(self._z_level_count): @@ -36,6 +58,15 @@ class Nd2(Nd2Parser): @property def image_sets(self): + """ + Iterates over groups of related images. This is useful if your ND2 contains multiple fields of view. + A typical use case might be that you have, say, four areas of interest that you're monitoring, and every + minute you take a bright field and GFP image of each one. For each cycle, this method would produce four + ImageSet objects, each containing one bright field and one GFP image. + + :return: model.ImageSet() + + """ for time_index in xrange(self._time_index_count): image_set = ImageSet() for fov in range(self._field_of_view_count): @@ -46,28 +77,28 @@ class Nd2(Nd2Parser): image_set.add(image) yield image_set - def get_image(self, time_index, fov, channel_name, z_level): - image_set_number = self._calculate_image_set_number(time_index, fov, z_level) + def get_image(self, time_index, field_of_view, channel_name, z_level): + """ + Returns an Image if data exists for the given parameters, otherwise returns None. In general, you should avoid + using this method unless you're very familiar with the structure of ND2 files. If you have a use case that + cannot be met by the `__iter__` or `image_sets` methods above, please create an issue on Github. + + :param time_index: the frame number + :type time_index: int + :param field_of_view: the label for the place in the XY-plane where this image was taken. + :type field_of_view: int + :param channel_name: the name of the color of this image + :type channel_name: str + :param z_level: the label for the location in the Z-plane where this image was taken. + :type z_level: int + :rtype: nd2reader.model.Image() or None + + """ + image_set_number = self._calculate_image_set_number(time_index, field_of_view, z_level) try: timestamp, raw_image_data = self._get_raw_image_data(image_set_number, self._channel_offset[channel_name]) - image = Image(timestamp, raw_image_data, fov, channel_name, z_level, self.height, self.width) + image = Image(timestamp, raw_image_data, field_of_view, channel_name, z_level, self.height, self.width) except TypeError: return None else: - return image - - @property - def height(self): - """ - :return: height of each image, in pixels - - """ - return self.metadata['ImageAttributes']['SLxImageAttributes']['uiHeight'] - - @property - def width(self): - """ - :return: width of each image, in pixels - - """ - return self.metadata['ImageAttributes']['SLxImageAttributes']['uiWidth'] + return image \ No newline at end of file