Browse Source

#123: created label map object, which parses the pointers to locations in the file where data is stored

feature/load_slices
jim 9 years ago
parent
commit
9548b92957
2 changed files with 144 additions and 18 deletions
  1. +121
    -0
      nd2reader/model/label.py
  2. +23
    -18
      nd2reader/parser/v3.py

+ 121
- 0
nd2reader/model/label.py View File

@ -0,0 +1,121 @@
import six
import struct
from collections import namedtuple
import re
data_location = namedtuple("DataLocation", ["location", "length"])
class LabelMap(object):
"""
"""
def __init__(self, raw_binary_data):
self._data = raw_binary_data
def _get_location(self, label):
try:
label_location = self._data.index(label) + len(label)
return self._parse_data_location(label_location)
except ValueError:
return None
def _parse_data_location(self, label_location):
location, length = struct.unpack("QQ", self._data[label_location: label_location + 16])
return data_location(location=location, length=length)
@property
def image_text_info(self):
return self._get_location(six.b("ImageTextInfoLV!"))
@property
def image_metadata_sequence(self):
# 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!"))
@property
def image_data(self):
image_data = {}
regex = re.compile(six.b("""ImageDataSeq\|(\d+)!"""))
for match in regex.finditer(self._data):
if match:
print(match.start(), match.end())
location = self._parse_data_location(match.end())
image_data[int(match.group(1))] = location
return image_data
@property
def image_calibration(self):
return self._get_location(six.b("ImageCalibrationLV|0!"))
@property
def image_attributes(self):
return self._get_location(six.b("ImageAttributesLV!"))
@property
def x_data(self):
return self._get_location(six.b("CustomData|X!"))
@property
def y_data(self):
return self._get_location(six.b("CustomData|Y!"))
@property
def z_data(self):
return self._get_location(six.b("CustomData|Z!"))
@property
def roi_metadata(self):
return self._get_location(six.b("CustomData|RoiMetadata_v1!"))
@property
def pfs_status(self):
return self._get_location(six.b("CustomData|PFS_STATUS!"))
@property
def pfs_offset(self):
return self._get_location(six.b("CustomData|PFS_OFFSET!"))
@property
def guid(self):
return self._get_location(six.b("CustomData|GUIDStore!"))
@property
def description(self):
return self._get_location(six.b("CustomData|CustomDescriptionV1_0!"))
@property
def camera_exposure_time(self):
return self._get_location(six.b("CustomData|Camera_ExposureTime1!"))
@property
def camera_temp(self):
return self._get_location(six.b("CustomData|CameraTemp1!"))
@property
def acquisition_times(self):
return self._get_location(six.b("CustomData|AcqTimesCache!"))
@property
def acquisition_times_2(self):
return self._get_location(six.b("CustomData|AcqTimes2Cache!"))
@property
def acquisition_frames(self):
return self._get_location(six.b("CustomData|AcqFramesCache!"))
@property
def lut_data(self):
return self._get_location(six.b("CustomDataVar|LUTDataV1_0!"))
@property
def grabber_settings(self):
return self._get_location(six.b("CustomDataVar|GrabberCameraSettingsV1_0!"))
@property
def custom_data(self):
return self._get_location(six.b("CustomDataVar|CustomDataV2_0!"))
@property
def app_info(self):
return self._get_location(six.b("CustomDataVar|AppInfo_V1_0!"))

+ 23
- 18
nd2reader/parser/v3.py View File

@ -3,6 +3,7 @@
import array import array
from datetime import datetime from datetime import datetime
from nd2reader.model.metadata import Metadata from nd2reader.model.metadata import Metadata
from nd2reader.model.label import LabelMap
from nd2reader.parser.base import BaseParser from nd2reader.parser.base import BaseParser
from nd2reader.driver.v3 import V3Driver from nd2reader.driver.v3 import V3Driver
from nd2reader.common.v3 import read_chunk from nd2reader.common.v3 import read_chunk
@ -40,11 +41,7 @@ class V3Parser(BaseParser):
def driver(self): def driver(self):
return V3Driver(self.metadata, self._label_map, self._fh) return V3Driver(self.metadata, self._label_map, self._fh)
def _parse_metadata(self):
"""
Reads all metadata and instantiates the Metadata object.
"""
def _build_metadata_dict(self):
metadata_dict = {} metadata_dict = {}
self._label_map = self._build_label_map() self._label_map = self._build_label_map()
for label in self._label_map.keys(): for label in self._label_map.keys():
@ -52,7 +49,14 @@ class V3Parser(BaseParser):
data = read_chunk(self._fh, self._label_map[label]) data = read_chunk(self._fh, self._label_map[label])
stop = label.index(six.b("LV")) stop = label.index(six.b("LV"))
metadata_dict[label[:stop]] = self._read_metadata(data, 1) metadata_dict[label[:stop]] = self._read_metadata(data, 1)
return metadata_dict
def _parse_metadata(self):
"""
Reads all metadata and instantiates the Metadata object.
"""
metadata_dict = self._build_metadata_dict()
height = metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiHeight')] height = metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiHeight')]
width = metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiWidth')] width = metadata_dict[six.b('ImageAttributes')][six.b('SLxImageAttributes')][six.b('uiWidth')]
channels = self._parse_channels(metadata_dict) channels = self._parse_channels(metadata_dict)
@ -208,23 +212,24 @@ class V3Parser(BaseParser):
:rtype: dict :rtype: dict
""" """
label_map = {}
# label_map = {}
self._fh.seek(-8, 2) self._fh.seek(-8, 2)
chunk_map_start_location = struct.unpack("Q", self._fh.read(8))[0] chunk_map_start_location = struct.unpack("Q", self._fh.read(8))[0]
self._fh.seek(chunk_map_start_location) self._fh.seek(chunk_map_start_location)
raw_text = self._fh.read(-1) raw_text = self._fh.read(-1)
label_start = raw_text.index(V3Parser.CHUNK_MAP_START) + 32
while True:
data_start = raw_text.index(six.b("!"), label_start) + 1
key = raw_text[label_start: data_start]
location, length = struct.unpack("QQ", raw_text[data_start: data_start + 16])
if key == V3Parser.CHUNK_MAP_END:
# We've reached the end of the chunk map
break
label_map[key] = location
label_start = data_start + 16
return label_map
# label_start = raw_text.index(V3Parser.CHUNK_MAP_START) + 32
return LabelMap(raw_text)
# while True:
# data_start = raw_text.index(six.b("!"), label_start) + 1
# key = raw_text[label_start: data_start]
# location, length = struct.unpack("QQ", raw_text[data_start: data_start + 16])
# if key == V3Parser.CHUNK_MAP_END:
# # We've reached the end of the chunk map
# break
# label_map[key] = location
# label_start = data_start + 16
# return label_map
def _parse_unsigned_char(self, data): def _parse_unsigned_char(self, data):
return struct.unpack("B", data.read(1))[0] return struct.unpack("B", data.read(1))[0]


Loading…
Cancel
Save