def get_image_by_attributes(self, frame_number, field_of_view, channel_name, z_level, height, width): """ Attempts to get Image based on attributes alone. :type frame_number: int :type field_of_view: int :type channel_name: str :type z_level: int :type height: int :type width: int :rtype: Image or None """ image_group_number = self._calculate_image_group_number(frame_number, field_of_view, z_level) try: timestamp, raw_image_data = self._get_raw_image_data(image_group_number, self._channel_offset[channel_name], height, width) image = Image(raw_image_data) image.add_params(image_group_number, timestamp, frame_number, field_of_view, channel_name, z_level) except (TypeError, NoImageError): return None else: return image
class ImageTests(unittest.TestCase): """ Basically just tests that the Image API works and that Images act as Numpy arrays. There's very little going on here other than simply storing data. """ def setUp(self): array = np.array([[0, 1, 254], [45, 12, 9], [12, 12, 99]]) self.image = Image(array) self.image.add_params(1200.314, 17, 2, 'GFP', 1) def test_size(self): self.assertEqual(self.image.height, 3) self.assertEqual(self.image.width, 3) def test_timestamp(self): self.assertEqual(self.image.timestamp, 1.200314) def test_frame_number(self): self.assertEqual(self.image.frame_number, 17) def test_fov(self): self.assertEqual(self.image.field_of_view, 2) def test_channel(self): self.assertEqual(self.image.channel, 'GFP') def test_z_level(self): self.assertEqual(self.image.z_level, 1) def test_slice(self): subimage = self.image[:2, :2] expected = np.array([[0, 1], [45, 12]]) self.assertTrue(np.array_equal(subimage, expected))
def get_image_by_attributes(self, frame_number, field_of_view, channel_name, z_level, height, width): """ Attempts to get Image based on attributes alone. :type frame_number: int :type field_of_view: int :type channel_name: str :type z_level: int :type height: int :type width: int :rtype: Image or None """ image_group_number = self._calculate_image_group_number( frame_number, field_of_view, z_level) try: timestamp, raw_image_data = self._get_raw_image_data( image_group_number, self._channel_offset[channel_name], height, width) image = Image(raw_image_data) image.add_params(image_group_number, timestamp, frame_number, field_of_view, channel_name, z_level) except (TypeError, NoImageError): return None else: return image
def _get_raw_image_data(self, image_group_number, channel_offset, height, width): """ Reads the raw bytes and the timestamp of an image. :param image_group_number: groups are made of images with the same time index, field of view and z-level. :type image_group_number: int :param channel_offset: the offset in the array where the bytes for this image are found. :type channel_offset: int :return: (int, array.array()) or None """ chunk = self._label_map[six.b("ImageDataSeq|%d!" % image_group_number)] data = read_chunk(self._file_handle, chunk) # All images in the same image group share the same timestamp! So if you have complicated image data, # your timestamps may not be entirely accurate. Practically speaking though, they'll only be off by a few # seconds unless you're doing something super weird. timestamp = struct.unpack("d", data[:8])[0] image_group_data = array.array("H", data) image_data_start = 4 + channel_offset # 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 # a data structure that way, please send the author of this library a message. image_data = np.reshape(image_group_data[image_data_start::len(self._metadata.channels)], (height, width)) # 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 # 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, Image(image_data) raise NoImageError
def setUp(self): array = np.array([[0, 1, 254], [45, 12, 9], [12, 12, 99]]) self.image = Image(array) self.image.add_params(1200.314, 17, 2, 'GFP', 1)