Browse Source

Merge pull request #136 from jimrybarski/135-tidy-up-for-publication

resolves #135. we're ready to publish version 2.0.0
zolfa-add_slices_loading
Jim Rybarski 9 years ago
parent
commit
1dab7e4e6f
7 changed files with 72 additions and 53 deletions
  1. +18
    -4
      CHANGELOG.md
  2. +3
    -1
      nd2reader/__init__.py
  3. +18
    -12
      nd2reader/main.py
  4. +1
    -0
      nd2reader/model/metadata.py
  5. +5
    -8
      nd2reader/parser/base.py
  6. +26
    -27
      nd2reader/parser/v3.py
  7. +1
    -1
      test.py

+ 18
- 4
CHANGELOG.md View File

@ -1,3 +1,17 @@
## [2.0.0] - 2015-12-20
### ADDED
- `select()` method to rapidly iterate over a subset of images matching certain criteria
- We parse metadata relating to the physical camera used to produce the images
- Raw metadata can be accessed conveniently, to allow contributors to find more interesting things to add
- An XML parsing library was added since the raw metadata contains some XML blocks
- The version number is now available in the nd2reader module
- Created a DOI to allow citation of the code
### REMOVED
- The `ImageGroup` container object
- The `data` attribute on Images. Images now inherit from ndarray, making this redundant
- The `image_sets` iterator
## [1.1.4] - 2015-10-27 ## [1.1.4] - 2015-10-27
### FIXED ### FIXED
- Implemented missing get_image_by_attributes method - Implemented missing get_image_by_attributes method
@ -9,16 +23,16 @@
## [1.1.2] - 2015-10-09 ## [1.1.2] - 2015-10-09
### ADDED ### ADDED
- `Image` objects now have a `frame_number` attribute. - `Image` objects now have a `frame_number` attribute.
- `Nd2` can be used as a context manager.
- `Nd2` can be used as a context manager
- More unit tests and functional tests - More unit tests and functional tests
### CHANGED ### CHANGED
- `Image` objects now directly subclass Numpy arrays.
- `Image` objects now directly subclass Numpy arrays
- Refactored code to permit parsing of different versions of ND2s, which will allow us to add support for NIS Elements 3.x. - Refactored code to permit parsing of different versions of ND2s, which will allow us to add support for NIS Elements 3.x.
### DEPRECATED ### DEPRECATED
- The `data` attribute is no longer needed since `Image` is now a Numpy array.
- The `image_sets` iterator will be removed in the near future. You should implement this yourself.
- The `data` attribute is no longer needed since `Image` is now a Numpy array
- The `image_sets` iterator will be removed in the near future. You should implement this yourself
## [1.1.1] - 2015-09-02 ## [1.1.1] - 2015-09-02
### FIXED ### FIXED


+ 3
- 1
nd2reader/__init__.py View File

@ -1 +1,3 @@
from nd2reader.interface import Nd2
from nd2reader.main import Nd2
__version__ = '2.0.0'

nd2reader/interface.py → nd2reader/main.py View File


+ 1
- 0
nd2reader/model/metadata.py View File

@ -99,6 +99,7 @@ class Metadata(object):
class CameraSettings(object): class CameraSettings(object):
""" Contains some basic information about a physical camera and its settings. """
def __init__(self, name, id, exposure, x_binning, y_binning, channel_name): def __init__(self, name, id, exposure, x_binning, y_binning, channel_name):
self.name = name.decode("utf8") self.name = name.decode("utf8")
self.id = id.decode("utf8") self.id = id.decode("utf8")


+ 5
- 8
nd2reader/parser/base.py View File

@ -2,18 +2,15 @@ from abc import abstractproperty
class BaseParser(object): class BaseParser(object):
@abstractproperty
def metadata(self):
"""
Instantiates a Metadata object.
"""
raise NotImplementedError
def __init__(self, fh):
self._fh = fh
self.camera_metadata = None
self.metadata = None
@abstractproperty @abstractproperty
def driver(self): def driver(self):
""" """
Instantiates a driver object.
Must return an object that can look up and read images.
""" """
raise NotImplementedError raise NotImplementedError

+ 26
- 27
nd2reader/parser/v3.py View File

@ -135,36 +135,32 @@ class V3Parser(BaseParser):
:type fh: file :type fh: file
""" """
self._fh = fh
self._metadata = None
self._raw_metadata = None
self._label_map = None
self._camera_metadata = {}
if six.PY3:
super().__init__(fh)
else:
super(V3Parser, self).__init__(fh)
self._label_map = self._build_label_map()
self.raw_metadata = V3RawMetadata(self._fh, self._label_map)
self._parse_camera_metadata()
self._parse_metadata() self._parse_metadata()
@property
def camera_metadata(self):
return self._camera_metadata
@property @property
def driver(self): def driver(self):
return V3Driver(self.metadata, self._label_map, self._fh)
@property
def metadata(self):
""" """
:rtype: Metadata
Provides an object that knows how to look up and read images based on an index.
""" """
return self._metadata
return V3Driver(self.metadata, self._label_map, self._fh)
@property
def raw_metadata(self):
if not self._raw_metadata:
self._label_map = self._build_label_map()
self._raw_metadata = V3RawMetadata(self._fh, self._label_map)
return self._raw_metadata
def _parse_camera_metadata(self):
"""
Gets parsed data about the physical cameras used to produce images and throws them in a dictionary.
"""
self.camera_metadata = {}
for camera_setting in self._parse_camera_settings():
self.camera_metadata[camera_setting.channel_name] = camera_setting
def _parse_metadata(self): def _parse_metadata(self):
""" """
Reads all metadata and instantiates the Metadata object. Reads all metadata and instantiates the Metadata object.
@ -177,14 +173,17 @@ class V3Parser(BaseParser):
frames = self._parse_frames(self.raw_metadata) frames = self._parse_frames(self.raw_metadata)
z_levels = self._parse_z_levels(self.raw_metadata) z_levels = self._parse_z_levels(self.raw_metadata)
total_images_per_channel = self._parse_total_images_per_channel(self.raw_metadata) total_images_per_channel = self._parse_total_images_per_channel(self.raw_metadata)
channels = []
for camera_setting in self._parse_camera_settings():
channels.append(camera_setting.channel_name)
self._camera_metadata[camera_setting.channel_name] = camera_setting
self._metadata = Metadata(height, width, sorted(list(channels)), date, fields_of_view, frames, z_levels, total_images_per_channel)
channels = sorted([key for key in self.camera_metadata.keys()])
self.metadata = Metadata(height, width, channels, date, fields_of_view, frames, z_levels, total_images_per_channel)
def _parse_camera_settings(self): def _parse_camera_settings(self):
for camera in self._raw_metadata.image_metadata_sequence[six.b('SLxPictureMetadata')][six.b('sPicturePlanes')][six.b('sSampleSetting')].values():
"""
Looks up information in the raw metadata about the camera(s) and puts it into a CameraSettings object.
Duplicate cameras can be returned if the same one was used for multiple channels.
:return:
"""
for camera in self.raw_metadata.image_metadata_sequence[six.b('SLxPictureMetadata')][six.b('sPicturePlanes')][six.b('sSampleSetting')].values():
name = camera[six.b('pCameraSetting')][six.b('CameraUserName')] name = camera[six.b('pCameraSetting')][six.b('CameraUserName')]
id = camera[six.b('pCameraSetting')][six.b('CameraUniqueName')] id = camera[six.b('pCameraSetting')][six.b('CameraUniqueName')]
exposure = camera[six.b('dExposureTime')] exposure = camera[six.b('dExposureTime')]


+ 1
- 1
test.py View File

@ -2,4 +2,4 @@ import unittest
loader = unittest.TestLoader() loader = unittest.TestLoader()
tests = loader.discover('tests', pattern='*.py', top_level_dir='.') tests = loader.discover('tests', pattern='*.py', top_level_dir='.')
testRunner = unittest.TextTestRunner() testRunner = unittest.TextTestRunner()
testRunner.run(tests)
testRunner.run(tests)

Loading…
Cancel
Save