Browse Source

#2 finished comments and cleanup of image and image set

master
Jim Rybarski 10 years ago
parent
commit
e6471f5a1f
1 changed files with 74 additions and 20 deletions
  1. +74
    -20
      nd2reader/model/__init__.py

+ 74
- 20
nd2reader/model/__init__.py View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
import collections
import numpy as np
import logging
@ -7,6 +9,25 @@ log = logging.getLogger(__name__)
class Image(object):
def __init__(self, timestamp, raw_array, field_of_view, channel, z_level, height, width):
"""
A wrapper around the raw pixel data of an image.
:param timestamp: The number of milliseconds after the beginning of the acquisition that this image was taken.
:type timestamp: int
:param raw_array: The raw sequence of bytes that represents the image.
:type raw_array: array.array()
: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: The name of the color of this image
:type channel: str
:param z_level: The label for the location in the Z-plane where this image was taken.
:type z_level: int
:param height: The height of the image in pixels.
:type height: int
:param width: The width of the image in pixels.
:type width: int
"""
self._timestamp = timestamp
self._raw_data = raw_array
self._field_of_view = field_of_view
@ -25,8 +46,28 @@ class Image(object):
"Z-Level: %s" % self.z_level,
])
@property
def data(self):
"""
The actual image data.
:rtype np.array()
"""
if self._data is None:
# The data is just a 1-dimensional array originally.
# We convert it to a 2D image here.
self._data = np.reshape(self._raw_data, (self._height, self._width))
return self._data
@property
def field_of_view(self):
"""
Which of the fixed locations this image was taken at.
:rtype int:
"""
return self._field_of_view
@property
@ -37,56 +78,69 @@ class Image(object):
timestamp. No, this doesn't make much sense. But that's how ND2s are structured, so if your experiment depends
on millisecond accuracy, you need to find an alternative imaging system.
:rtype float:
"""
return self._timestamp / 1000.0
@property
def channel(self):
"""
The name of the filter used to acquire this image. These are user-supplied in NIS Elements.
:rtype str:
"""
return self._channel
@property
def z_level(self):
return self._z_level
"""
The vertical offset of the image. These are simple integers starting from 0, where the 0 is the lowest
z-level and each subsequent level incremented by 1.
@property
def data(self):
if self._data is None:
# The data is just a flat, 1-dimensional array. We convert it to a 2D image here.
self._data = np.reshape(self._raw_data, (self._height, self._width))
return self._data
For example, if you acquired images at -3 µm, 0 µm, and +3 µm, your z-levels would be:
-3 µm: 0
0 µm: 1
+3 µm: 2
:rtype int:
"""
return self._z_level
class ImageSet(object):
"""
A group of images that share the same timestamp. NIS Elements doesn't store a unique timestamp for every
image, rather, it stores one for each set of images that share the same field of view and z-axis level.
A group of images that were taken at roughly the same time.
"""
def __init__(self):
self._images = collections.defaultdict(dict)
def __len__(self):
""" The number of images in the image set. """
return sum([len(channel) for channel in self._images.values()])
def __repr__(self):
return "\n".join(["<ND2 Image Set>",
"Image count: %s" % len(self)])
def get(self, channel="", z_level=0):
def get(self, channel, z_level=0):
"""
Retrieve an image with a given channel and z-level. For most users, z_level will always be 0.
"""
try:
image = self._images[channel][z_level]
except KeyError:
return None
else:
return image
:type channel: str
:type z_level: int
def __len__(self):
""" The number of images in the image set. """
return sum([len(channel) for channel in self._images.values()])
"""
return self._images.get(channel).get(z_level)
def add(self, image):
"""
Stores an image.
:type image: nd2reader.model.Image()
"""

Loading…
Cancel
Save