From c61f6f0b26a99e67e232f78303e59d563651bc67 Mon Sep 17 00:00:00 2001 From: jim Date: Mon, 22 Dec 2014 15:38:39 -0600 Subject: [PATCH 1/2] fixed error where non-deleted fields of view woudn't work --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 8ff9ed8..1556d3e 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages setup( name="nd2reader", packages=find_packages(), - version="0.9.0", + version="0.9.5", install_requires=[ 'numpy', ], From 5ef69bca41933589354e175ee9294920a9399434 Mon Sep 17 00:00:00 2001 From: jim Date: Tue, 27 Jan 2015 18:17:31 -0600 Subject: [PATCH 2/2] resolves #1 hopefully --- nd2reader/service/__init__.py | 63 ++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/nd2reader/service/__init__.py b/nd2reader/service/__init__.py index c93079f..e03b068 100644 --- a/nd2reader/service/__init__.py +++ b/nd2reader/service/__init__.py @@ -1,6 +1,9 @@ +# -*- coding: utf-8 -*- + import array import numpy as np import struct +import re from StringIO import StringIO from collections import namedtuple import logging @@ -69,12 +72,11 @@ class BaseNd2(object): :rtype: int """ - return self._image_count / self.field_of_view_count / self.z_level_count + return self._reader.time_index_count @property def z_level_count(self): - # return self._image_count / self._sequence_count - return 3 + return self._reader.z_level_count @property def field_of_view_count(self): @@ -85,11 +87,7 @@ class BaseNd2(object): NIS Elements can figure it out, but we haven't found it yet. """ - try: - valid_fovs = self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx'][''][0]['pItemValid'] - except KeyError: - valid_fovs = self._metadata['ImageMetadata']['SLxExperiment']['ppNextLevelEx']['']['pItemValid'] - return sum(valid_fovs) + return self._reader.field_of_view_count @property def channel_count(self): @@ -124,6 +122,23 @@ class Nd2Reader(object): self._metadata = {} self._read_map() self._parse_dict_data() + self.__dimensions = None + + @property + def _dimensions(self): + if self.__dimensions is None: + # TODO: Replace this with a single regex + for line in self._metadata['ImageTextInfo']['SLxImageTextInfo'].values(): + if "Dimensions:" in line: + metadata = line + break + else: + raise Exception("Could not parse metadata dimensions!") + for line in metadata.split("\r\n"): + if line.startswith("Dimensions:"): + self.__dimensions = line + break + return self.__dimensions @property def fh(self): @@ -131,9 +146,39 @@ class Nd2Reader(object): self._file_handler = open(self._filename, "rb") return self._file_handler + @property + def time_index_count(self): + """ + The number of images for a given field of view, channel, and z_level combination. + Effectively the number of frames. + + :rtype: int + + """ + pattern = r""".*?T'\((\d+)\).*?""" + return int(re.match(pattern, self._dimensions).group(1)) + + @property + def z_level_count(self): + pattern = r""".*?Z\((\d+)\).*?""" + return int(re.match(pattern, self._dimensions).group(1)) + + @property + def field_of_view_count(self): + """ + The metadata contains information about fields of view, but it contains it even if some fields + of view were cropped. We can't find anything that states which fields of view are actually + in the image data, so we have to calculate it. There probably is something somewhere, since + NIS Elements can figure it out, but we haven't found it yet. + + """ + pattern = r""".*?XY\((\d+)\).*?""" + return int(re.match(pattern, self._dimensions).group(1)) + @property def channel_count(self): - return self._metadata['ImageAttributes']["SLxImageAttributes"]["uiComp"] + pattern = r""".*?λ\((\d+)\).*?""" + return int(re.match(pattern, self._dimensions).group(1)) def get_raw_image_data(self, image_set_number, channel_offset): chunk = self._label_map["ImageDataSeq|%d!" % image_set_number]