Browse Source

resolves #123: the label map and raw metadata are now accessible, so we can more easily compare what they contain to the information in the XML (which we're still not parsing)

zolfa-add_slices_loading
jim 9 years ago
parent
commit
4943a854f1
4 changed files with 24 additions and 17 deletions
  1. +7
    -0
      functional_tests/single.py
  2. +1
    -1
      nd2reader/driver/v3.py
  3. +9
    -9
      nd2reader/model/label.py
  4. +7
    -7
      nd2reader/parser/v3.py

+ 7
- 0
functional_tests/single.py View File

@ -25,6 +25,13 @@ class FunctionalTests(unittest.TestCase):
def test_length(self): def test_length(self):
self.assertEqual(len(self.nd2), 1) self.assertEqual(len(self.nd2), 1)
def test_actual_length(self):
count = 0
for image in self.nd2:
if image is not None:
count += 1
self.assertEqual(len(self.nd2), count)
def test_frames(self): def test_frames(self):
self.assertEqual(len(self.nd2.frames), 1) self.assertEqual(len(self.nd2.frames), 1)


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

@ -130,7 +130,7 @@ class V3Driver(object):
:raises: NoImageError :raises: NoImageError
""" """
chunk = self._label_map[six.b("ImageDataSeq|%d!" % image_group_number)]
chunk = self._label_map.get_image_data_location(image_group_number)
data = read_chunk(self._file_handle, chunk) 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, # 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 # your timestamps may not be entirely accurate. Practically speaking though, they'll only be off by a few


+ 9
- 9
nd2reader/model/label.py View File

@ -8,6 +8,7 @@ class LabelMap(object):
""" """
def __init__(self, raw_binary_data): def __init__(self, raw_binary_data):
self._data = raw_binary_data self._data = raw_binary_data
self._image_data = {}
def _get_location(self, label): def _get_location(self, label):
try: try:
@ -33,15 +34,14 @@ class LabelMap(object):
# there is always only one of these, even though it has a pipe followed by a zero, which is how they do indexes # there is always only one of these, even though it has a pipe followed by a zero, which is how they do indexes
return self._get_location(six.b("ImageMetadataSeqLV|0!")) return self._get_location(six.b("ImageMetadataSeqLV|0!"))
@property
def image_data(self):
image_data = {}
regex = re.compile(six.b("""ImageDataSeq\|(\d+)!"""))
for match in regex.finditer(self._data):
if match:
location = self._parse_data_location(match.end())
image_data[int(match.group(1))] = location
return image_data
def get_image_data_location(self, index):
if not self._image_data:
regex = re.compile(six.b("""ImageDataSeq\|(\d+)!"""))
for match in regex.finditer(self._data):
if match:
location = self._parse_data_location(match.end())
self._image_data[int(match.group(1))] = location
return self._image_data[index]
@property @property
def image_calibration(self): def image_calibration(self):


+ 7
- 7
nd2reader/parser/v3.py View File

@ -77,8 +77,8 @@ class V3Parser(BaseParser):
""" """
metadata_dict = self._build_metadata_dict() metadata_dict = self._build_metadata_dict()
height = metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiHeight')]
width = metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiWidth')]
height = metadata_dict['image_attributes'][six.b('SLxImageAttributes')][six.b('uiHeight')]
width = metadata_dict['image_attributes'][six.b('SLxImageAttributes')][six.b('uiWidth')]
channels = self._parse_channels(metadata_dict) channels = self._parse_channels(metadata_dict)
date = self._parse_date(metadata_dict) date = self._parse_date(metadata_dict)
fields_of_view = self._parse_fields_of_view(metadata_dict) fields_of_view = self._parse_fields_of_view(metadata_dict)
@ -95,7 +95,7 @@ class V3Parser(BaseParser):
:rtype: datetime.datetime() or None :rtype: datetime.datetime() or None
""" """
for line in metadata_dict[six.b('ImageTextInfo')][six.b('SLxImageTextInfo')].values():
for line in metadata_dict['image_text_info'][six.b('SLxImageTextInfo')].values():
line = line.decode("utf8") line = line.decode("utf8")
absolute_start_12 = None absolute_start_12 = None
absolute_start_24 = None absolute_start_24 = None
@ -123,9 +123,9 @@ class V3Parser(BaseParser):
""" """
channels = [] channels = []
metadata = metadata_dict[six.b('ImageMetadataSeq')][six.b('SLxPictureMetadata')][six.b('sPicturePlanes')]
metadata = metadata_dict['image_metadata_sequence'][six.b('SLxPictureMetadata')][six.b('sPicturePlanes')]
try: try:
validity = metadata_dict[six.b('ImageMetadata')][six.b('SLxExperiment')][six.b('ppNextLevelEx')][six.b('')][0][six.b('ppNextLevelEx')][six.b('')][0][six.b('pItemValid')]
validity = metadata_dict['image_metadata'][six.b('SLxExperiment')][six.b('ppNextLevelEx')][six.b('')][0][six.b('ppNextLevelEx')][six.b('')][0][six.b('pItemValid')]
except KeyError: except KeyError:
# If none of the channels have been deleted, there is no validity list, so we just make one # If none of the channels have been deleted, there is no validity list, so we just make one
validity = [True for _ in metadata] validity = [True for _ in metadata]
@ -181,7 +181,7 @@ class V3Parser(BaseParser):
:rtype: str :rtype: str
""" """
for line in metadata_dict[six.b('ImageTextInfo')][six.b('SLxImageTextInfo')].values():
for line in metadata_dict['image_text_info'][six.b('SLxImageTextInfo')].values():
if six.b("Dimensions:") in line: if six.b("Dimensions:") in line:
metadata = line metadata = line
break break
@ -221,7 +221,7 @@ class V3Parser(BaseParser):
:rtype: int :rtype: int
""" """
return metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiSequenceCount')]
return metadata_dict['image_attributes'][six.b('SLxImageAttributes')][six.b('uiSequenceCount')]
def _build_label_map(self): def _build_label_map(self):
""" """


Loading…
Cancel
Save