Browse Source

resolves #39

zolfa-add_slices_loading
Jim Rybarski 9 years ago
parent
commit
89ddce3a7b
3 changed files with 39 additions and 55 deletions
  1. +37
    -53
      nd2reader/__init__.py
  2. +1
    -1
      nd2reader/parser.py
  3. +1
    -1
      setup.py

+ 37
- 53
nd2reader/__init__.py View File

@ -34,64 +34,20 @@ class Nd2(Nd2Parser):
""" """
return self._image_count * self._channel_count return self._image_count * self._channel_count
@property
def height(self):
"""
:return: height of each image, in pixels
:rtype: int
"""
return self.metadata[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiHeight')]
@property
def width(self):
"""
:return: width of each image, in pixels
:rtype: int
"""
return self.metadata[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('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 self._fields_of_view:
for z_level in self._z_levels:
for channel_name in self._channels:
image = self.get_image(i, fov, channel_name, z_level)
if image is not None:
yield image
def __getitem__(self, item):
if isinstance(item, int):
def __getitem__(self, frame_number):
if isinstance(frame_number, int):
try: try:
channel_offset = item % len(self.channels)
fov = self._calculate_field_of_view(item)
channel = self._calculate_channel(item)
z_level = self._calculate_z_level(item)
item -= channel_offset
item /= len(self.channels)
timestamp, raw_image_data = self._get_raw_image_data(item, channel_offset)
channel_offset = frame_number % len(self.channels)
fov = self._calculate_field_of_view(frame_number)
channel = self._calculate_channel(frame_number)
z_level = self._calculate_z_level(frame_number)
timestamp, raw_image_data = self._get_raw_image_data(frame_number, channel_offset)
image = Image(timestamp, raw_image_data, fov, channel, z_level, self.height, self.width) image = Image(timestamp, raw_image_data, fov, channel, z_level, self.height, self.width)
except TypeError:
except (TypeError, ValueError):
return None return None
else: else:
return image return image
def _calculate_field_of_view(self, frame_number):
return int((frame_number - (frame_number % (len(self.z_levels) * len(self.channels)))) / (len(self.z_levels) * len(self.channels)))
def _calculate_channel(self, frame_number):
return self._channels[frame_number % len(self.channels)]
def _calculate_z_level(self, frame_number):
return self.z_levels[int(((frame_number - (frame_number % len(self.channels))) / 2) % len(self.z_levels))]
@property @property
def image_sets(self): def image_sets(self):
""" """
@ -103,7 +59,7 @@ class Nd2(Nd2Parser):
:return: model.ImageSet() :return: model.ImageSet()
""" """
for time_index in self._time_indexes:
for time_index in self.time_indexes:
image_set = ImageSet() image_set = ImageSet()
for fov in self._fields_of_view: for fov in self._fields_of_view:
for channel_name in self._channels: for channel_name in self._channels:
@ -113,6 +69,34 @@ class Nd2(Nd2Parser):
image_set.add(image) image_set.add(image)
yield image_set yield image_set
@property
def height(self):
"""
:return: height of each image, in pixels
:rtype: int
"""
return self.metadata[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiHeight')]
@property
def width(self):
"""
:return: width of each image, in pixels
:rtype: int
"""
return self.metadata[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiWidth')]
def _calculate_field_of_view(self, frame_number):
images_per_cycle = len(self.z_levels) * len(self.channels)
return int((frame_number - (frame_number % images_per_cycle)) / images_per_cycle) % len(self.fields_of_view)
def _calculate_channel(self, frame_number):
return self._channels[frame_number % len(self.channels)]
def _calculate_z_level(self, frame_number):
return self.z_levels[int(((frame_number - (frame_number % len(self.channels))) / len(self.channels)) % len(self.z_levels))]
def get_image(self, time_index, field_of_view, channel_name, 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 Returns an Image if data exists for the given parameters, otherwise returns None. In general, you should avoid


+ 1
- 1
nd2reader/parser.py View File

@ -63,7 +63,7 @@ class Nd2Parser(object):
# The images for the various channels are interleaved within the same array. For example, the second image # The images for the various channels are interleaved within the same array. For example, the second image
# of a four image group will be composed of bytes 2, 6, 10, etc. If you understand why someone would design # of a four image group will be composed of bytes 2, 6, 10, etc. If you understand why someone would design
# a data structure that way, please send the author of this library a message. # a data structure that way, please send the author of this library a message.
image_data = image_group_data[image_data_start::self._channel_count]
image_data = image_group_data[image_data_start::len(self.channels)]
# Skip images that are all zeros! This is important, since NIS Elements creates blank "gap" images if you # Skip images that are all zeros! This is important, since NIS Elements creates blank "gap" images if you
# don't have the same number of images each cycle. We discovered this because we only took GFP images every # don't have the same number of images each cycle. We discovered this because we only took GFP images every
# other cycle to reduce phototoxicity, but NIS Elements still allocated memory as if we were going to take # other cycle to reduce phototoxicity, but NIS Elements still allocated memory as if we were going to take


+ 1
- 1
setup.py View File

@ -1,6 +1,6 @@
from distutils.core import setup from distutils.core import setup
VERSION = "1.0.1"
VERSION = "1.1.0"
setup( setup(
name="nd2reader", name="nd2reader",


Loading…
Cancel
Save