Browse Source

resolves #114. added index to Images to help with testing. Increased test coverage for filter()

master
Jim Rybarski 9 years ago
parent
commit
f366f38009
4 changed files with 56 additions and 8 deletions
  1. +43
    -3
      functional_tests/FYLM141111001.py
  2. +2
    -2
      nd2reader/driver/v3.py
  3. +2
    -2
      nd2reader/interface.py
  4. +9
    -1
      nd2reader/model/image.py

+ 43
- 3
functional_tests/FYLM141111001.py View File

@ -7,6 +7,7 @@ from nd2reader import Nd2
import numpy as np import numpy as np
from datetime import datetime from datetime import datetime
import unittest import unittest
import six
class FunctionalTests(unittest.TestCase): class FunctionalTests(unittest.TestCase):
@ -108,18 +109,57 @@ class FunctionalTests(unittest.TestCase):
self.assertTupleEqual((self.nd2[54].z_level, self.nd2[54].channel), (0, 'BF')) self.assertTupleEqual((self.nd2[54].z_level, self.nd2[54].channel), (0, 'BF'))
def test_get_image_by_attribute_none(self): def test_get_image_by_attribute_none(self):
# Should handle missing images without an exception
image = self.nd2.get_image(4, 0, "GFP", 0) image = self.nd2.get_image(4, 0, "GFP", 0)
self.assertIsNone(image) self.assertIsNone(image)
def test_fast_filter(self):
def test_index(self):
# Do indexes get added to images properly?
for n, image in enumerate(self.nd2):
if image is not None:
self.assertEqual(n, image.index)
if n > 50:
break
def test_filter(self):
# If we take the first 20 GFP images, they should be identical to the first 20 items iterated from filter()
# if we set our criteria to just "GFP"
manual_images = [] manual_images = []
for _, image in zip(range(200), self.nd2):
for _, image in zip(range(20), self.nd2):
if image is not None and image.channel == 'GFP': if image is not None and image.channel == 'GFP':
manual_images.append(image) manual_images.append(image)
filter_images = [] filter_images = []
for image in self.nd2.filter(channels=['GFP']):
for image in self.nd2.filter(channels='GFP'):
filter_images.append(image) filter_images.append(image)
if len(filter_images) == len(manual_images): if len(filter_images) == len(manual_images):
break break
for a, b in zip(manual_images, filter_images): for a, b in zip(manual_images, filter_images):
self.assertTrue(np.array_equal(a, b)) self.assertTrue(np.array_equal(a, b))
def test_filter_order_all(self):
# If we select every possible image using filter(), we should just get every image in order
n = 0
for image in self.nd2.filter(channels=['BF', 'GFP'], z_levels=[0, 1, 2], fields_of_view=list(range(8))):
while True:
indexed_image = self.nd2[n]
if indexed_image is not None:
break
n += 1
self.assertTrue(np.array_equal(image, indexed_image))
n += 1
if n > 100:
break
def test_filter_order_subset(self):
# Test that images are always yielded in increasing order. This guarantees that no matter what subset of images
# we're filtering, we still get them in the chronological order they were acquired
n = -1
for image in self.nd2.filter(channels='BF', z_levels=[0, 1], fields_of_view=[1, 2, 4]):
self.assertGreater(image.index, n)
self.assertEqual(image.channel, 'BF')
self.assertIn(image.field_of_view, (1, 2, 4))
self.assertIn(image.z_level, (0, 1))
n = image.index
if n > 100:
break

+ 2
- 2
nd2reader/driver/v3.py View File

@ -102,7 +102,7 @@ class V3Driver(object):
except NoImageError: except NoImageError:
return None return None
else: else:
image.add_params(timestamp, frame_number, field_of_view, channel, z_level)
image.add_params(index, timestamp, frame_number, field_of_view, channel, z_level)
return image return image
@property @property
@ -169,7 +169,7 @@ class V3Driver(object):
height, height,
width) width)
image = Image(raw_image_data) image = Image(raw_image_data)
image.add_params(timestamp, frame_number, field_of_view, channel_name, z_level)
image.add_params(image_group_number, timestamp, frame_number, field_of_view, channel_name, z_level)
except (TypeError, NoImageError): except (TypeError, NoImageError):
return None return None
else: else:


+ 2
- 2
nd2reader/interface.py View File

@ -194,10 +194,10 @@ class Nd2(object):
z_levels = self._to_list(z_levels, self.z_levels) z_levels = self._to_list(z_levels, self.z_levels)
for frame in self.frames: for frame in self.frames:
for fov in fields_of_view:
for f in fields_of_view:
for z in z_levels: for z in z_levels:
for c in channels: for c in channels:
image = self.get_image(frame, fov, c, z)
image = self.get_image(frame, f, c, z)
if image is not None: if image is not None:
yield image yield image


+ 9
- 1
nd2reader/model/image.py View File

@ -12,14 +12,17 @@ class Image(np.ndarray):
return np.asarray(array).view(cls) return np.asarray(array).view(cls)
def __init__(self, array): def __init__(self, array):
self._index = None
self._timestamp = None self._timestamp = None
self._frame_number = None self._frame_number = None
self._field_of_view = None self._field_of_view = None
self._channel = None self._channel = None
self._z_level = None self._z_level = None
def add_params(self, timestamp, frame_number, field_of_view, channel, z_level):
def add_params(self, index, timestamp, frame_number, field_of_view, channel, z_level):
""" """
:param index: The integer that can be used to directly index this image
:type index: int
:param timestamp: The number of milliseconds after the beginning of the acquisition that this image was taken. :param timestamp: The number of milliseconds after the beginning of the acquisition that this image was taken.
:type timestamp: float :type timestamp: float
:param frame_number: The order in which this image was taken, with images of different channels/z-levels :param frame_number: The order in which this image was taken, with images of different channels/z-levels
@ -33,12 +36,17 @@ class Image(np.ndarray):
:type z_level: int :type z_level: int
""" """
self._index = index
self._timestamp = timestamp self._timestamp = timestamp
self._frame_number = int(frame_number) self._frame_number = int(frame_number)
self._field_of_view = field_of_view self._field_of_view = field_of_view
self._channel = channel self._channel = channel
self._z_level = z_level self._z_level = z_level
@property
def index(self):
return self._index
@property @property
def height(self): def height(self):
""" """


Loading…
Cancel
Save